gpt4 book ai didi

c# - 在 ASP.NET Core 3.1 中上传和下载大文件?

转载 作者:行者123 更新时间:2023-12-04 11:03:42 28 4
gpt4 key购买 nike

我正在使用干净的架构开发一个 ASP.NET Core 3.1 API 项目,并且我有以下类库(层):

  • 基础设施(安全内容和上传助手等...)
  • 持久性(DA 层)
  • 域(域模型)
  • 应用程序(用例 - 业务逻辑)
  • API(API项目作为我的启动项目)

  • 我要 能够上传大文件到服务器(如 2Gb 或更大的文件大小)然后下载它们并想要这样做 没有 future 的内存溢出和一切问题。
    任何帮助,将不胜感激。

    最佳答案

    如果你有那么大的文件,千万不要使用 byte[]MemoryStream在你的代码中。如果您下载/上传文件,则仅对流进行操作。
    你有几个选择:

  • 如果您同时控制客户端和服务器,请考虑使用类似 tus . .NET 有客户端实现和服务器实现。这可能是最简单和最强大的选择。
  • 如果您使用 HttpClient 上传大文件,只需使用 StreamContent类发送它们。同样,不要使用 MemoryStream作为来源,但其他类似 FileStream .
  • 如果您使用 HttpClient 下载大文件,请务必指定 HttpCompletionOptions,例如 var response = await httpClient.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead) .否则,HttpClient 会将整个响应缓冲在内存中。然后,您可以通过 var stream = response.Content.ReadAsStreamAsync() 将响应文件作为流处理。 .

  • ASP.NET Core 具体建议:
  • 如果要通过 HTTP POST 接收文件,则需要增加请求大小限制:[RequestSizeLimit(10L * 1024L * 1024L * 1024L)][RequestFormLimits(MultipartBodyLengthLimit = 10L * 1024L * 1024L * 1024L)] .另外,需要禁用表单值绑定(bind),否则整个请求会被缓存到内存中:
  •    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
    {
    public void OnResourceExecuting(ResourceExecutingContext context)
    {
    var factories = context.ValueProviderFactories;
    factories.RemoveType<FormValueProviderFactory>();
    factories.RemoveType<FormFileValueProviderFactory>();
    factories.RemoveType<JQueryFormValueProviderFactory>();
    }

    public void OnResourceExecuted(ResourceExecutedContext context)
    {
    }
    }
  • 要从 Controller 返回文件,只需通过 File 简单地返回它。方法,接受流:return File(stream, mimeType, fileName);

  • 一个示例 Controller 看起来像这样(见 https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-3.1 缺少的帮助类):
    private const MaxFileSize = 10L * 1024L * 1024L * 1024L; // 10GB, adjust to your need

    [DisableFormValueModelBinding]
    [RequestSizeLimit(MaxFileSize)]
    [RequestFormLimits(MultipartBodyLengthLimit = MaxFileSize)]
    public async Task ReceiveFile()
    {
    if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
    throw new BadRequestException("Not a multipart request");

    var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType));
    var reader = new MultipartReader(boundary, Request.Body);

    // note: this is for a single file, you could also process multiple files
    var section = await reader.ReadNextSectionAsync();

    if (section == null)
    throw new BadRequestException("No sections in multipart defined");

    if (!ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition))
    throw new BadRequestException("No content disposition in multipart defined");

    var fileName = contentDisposition.FileNameStar.ToString();
    if (string.IsNullOrEmpty(fileName))
    {
    fileName = contentDisposition.FileName.ToString();
    }

    if (string.IsNullOrEmpty(fileName))
    throw new BadRequestException("No filename defined.");

    using var fileStream = section.Body;
    await SendFileSomewhere(fileStream);
    }

    // This should probably not be inside the controller class
    private async Task SendFileSomewhere(Stream stream)
    {
    using var request = new HttpRequestMessage()
    {
    Method = HttpMethod.Post,
    RequestUri = new Uri("YOUR_DESTINATION_URI"),
    Content = new StreamContent(stream),
    };
    using var response = await _httpClient.SendAsync(request);
    // TODO check response status etc.
    }

    在此示例中,我们将整个文件流式传输到另一个服务。在某些情况下,最好将文件临时保存到磁盘上。

    关于c# - 在 ASP.NET Core 3.1 中上传和下载大文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62502286/

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