gpt4 book ai didi

asp.net-core - Asp.Net Core 5 API Web 以 WCF 等流模式上传大文件

转载 作者:行者123 更新时间:2023-12-05 02:43:34 25 4
gpt4 key购买 nike

我需要在使用 asp .net core 5 制作的网络服务器上以流模式(一次一个)上传一个大文件 (7GB)。

配置服务器端:

public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>().UseKestrel(options =>
{
options.Limits.MaxRequestBodySize = long.MaxValue;

});
});
}

服务器端的 Controller :

[HttpPost]
[RequestFormLimits(MultipartBodyLengthLimit = Int32.MaxValue)]
public async Task PostStream(IFormFile formFiles)
{
//rest of code
}

客户端(桌面应用)

using (var httpClient = new HttpClient())
{
using (var content = new MultipartFormDataContent())
{
string fileName = @"D:\largeFile.zip";

FileStream fileStream = File.OpenRead(fileName);
HttpContent fileStreamContent = new StreamContent(fileStream);

fileStreamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") { Name = "formFiles", FileName = fileName };
fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

content.Add(fileStreamContent);


var response = httpClient.PostAsync("http://localhost:5000/weatherforecast", content).Result;
response.EnsureSuccessStatusCode();
}

系统工作到 1 GB,大文件 (7GB) 服务器取消请求,我注意到发送到服务器的文件不是流式传输而是完全上传,我期待在服务器上进行渐进式上传,就像在 WCF 上发生的那样。如何逐步将文件发送到服务器?

最佳答案

因为你的服务器端代码

[HttpPost]
[RequestFormLimits(MultipartBodyLengthLimit = Int32.MaxValue)]
public async Task PostStream(IFormFile formFiles)
{
//rest of code
}

我假设你没有关注这个 tutorial然而。而且教程中的代码太多了,所以我将总结一下我所做的并在下面给你一个例子。

首先,您需要一个过滤器来禁用模型绑定(bind)。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
if (!RequestHelper.IsMultipartContentType(context.HttpContext.Request.ContentType))
{
context.Result = new BadRequestObjectResult("Request is not a 'multipart' request");
}

var factories = context.ValueProviderFactories;
factories.RemoveType<FormValueProviderFactory>();
factories.RemoveType<FormFileValueProviderFactory>();
factories.RemoveType<JQueryFormValueProviderFactory>();
}

public void OnResourceExecuted(ResourceExecutedContext context)
{
}
}

然后是处理上传请求的服务代码。确保稍微更改它以将文件保存到磁盘而不是内存中。

public class MultipartRequestService : IMultipartRequestService
{
public async Task<(Dictionary<string, StringValues>, byte[])> GetDataFromMultiPart(MultipartReader reader, CancellationToken cancellationToken)
{
var formAccumulator = new KeyValueAccumulator();
var file = new byte[0];

MultipartSection section;
while ((section = await reader.ReadNextSectionAsync(cancellationToken)) != null)
{
if (!ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition))
{
continue;
}

if (contentDisposition.IsFormDisposition())
{
formAccumulator = await AccumulateForm(formAccumulator, section, contentDisposition);
}

else if (contentDisposition.IsFileDisposition())
{
// you will want to replace all of this because it copies the file into a memory stream. We don't want that.
await using var memoryStream = new MemoryStream();
await section.Body.CopyToAsync(memoryStream, cancellationToken);

file = memoryStream.ToArray();
}
}

return (formAccumulator.GetResults(), file);
}

private Encoding GetEncoding(MultipartSection section)
{
var hasMediaTypeHeader = MediaTypeHeaderValue.TryParse(section.ContentType, out var mediaType);

// UTF-7 is insecure and shouldn't be honored. UTF-8 succeeds in
// most cases.
if (!hasMediaTypeHeader || Encoding.UTF7.Equals(mediaType.Encoding))
{
return Encoding.UTF8;
}

return mediaType.Encoding;
}

private async Task<KeyValueAccumulator> AccumulateForm(KeyValueAccumulator formAccumulator, MultipartSection section, ContentDispositionHeaderValue contentDisposition)
{
var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name).Value;
using var streamReader = new StreamReader(section.Body, GetEncoding(section), true, 1024, true);
{
var value = await streamReader.ReadToEndAsync();
if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
{
value = string.Empty;
}
formAccumulator.Append(key, value);

if (formAccumulator.ValueCount > FormReader.DefaultValueCountLimit)
{
throw new InvalidDataException($"Form key count limit {FormReader.DefaultValueCountLimit} exceeded.");
}
}

return formAccumulator;
}
}

最后是 Controller 代码

[HttpPost()]
[DisableFormValueModelBinding]
public async Task<IActionResult> Upload(
[FromServices] IMultipartRequestService multipartRequestService,
CancellationToken cancellationToken)
{
var reader = new MultipartReader(HttpContext.Request.GetMultipartBoundary(), HttpContext.Request.Body)
{
BodyLengthLimit = uploadLimit.Value.ChunkSizeLimitInBytes
};

_logger.LogInformation("Read data and file from uploaded request");
var (forms, file) = await multipartRequestService.GetDataFromMultiPart(reader, cancellationToken);

// do anything you want

return Ok();
}

关于asp.net-core - Asp.Net Core 5 API Web 以 WCF 等流模式上传大文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66875753/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com