【问题标题】:Multipart body length limit exceeded exception多部分正文长度限制超出异常
【发布时间】:2016-11-01 16:23:36
【问题描述】:

尽管在web.config 部分中将MaxRequestLengthmaxAllowedContentLength 设置为可能的最大值,但ASP.Net Core 不允许我上传大于134,217,728 Bytes 的文件。来自网络服务器的确切错误是:

处理请求时发生未处理的异常。

InvalidDataException:超过多部分正文长度限制 134217728。

有没有办法解决这个问题? (ASP.Net 核心

【问题讨论】:

  • 你能发布异常堆栈跟踪吗?
  • @aguafrommars:我已经解决了这个问题,请检查我自己的答案。

标签: asp.net-core asp.net-core-mvc


【解决方案1】:

在阅读了 GitHub 上的一些帖子后,我找到了解决此问题的方法。结论是它们必须在Startup 类中设置。例如:

public void ConfigureServices(IServiceCollection services)
{
        services.AddMvc();
        services.Configure<FormOptions>(x => {
            x.ValueLengthLimit = int.MaxValue;
            x.MultipartBodyLengthLimit = int.MaxValue; // In case of multipart
        })
 }

这将解决问题。但是他们也表示有一个[RequestFormSizeLimit] 属性,但我还无法引用它。

【讨论】:

  • 感谢上帝,我找到了你,没有你我迷失了
  • 还有其他人无法在最新版本中使用它吗?
  • @JasonRowe 是的,我是。看起来它不适用于最新版本。
  • OP 没有提到 Azure 或 IIS。 IIS/Azure 确实从 web.config 文件中读取了一些设置。红隼没有。
  • 仍然收到错误消息(“超过多部分正文长度限制 1000000000”)。尝试将MultipartBodyLengthLimit 设置为long.MaxValue,但由于某种原因它被忽略了。
【解决方案2】:

或者使用该属性,因此 Transcendant 解决的操作的等价物是:

[RequestFormLimits(ValueLengthLimit = int.MaxValue, MultipartBodyLengthLimit = int.MaxValue)]

【讨论】:

    【解决方案3】:

    如果您按照其他答案中的建议使用 int.MaxValue (2,147,483,647) 作为 MultipartBodyLengthLimit 的值,则您将允许上传大约 10 个文件。 2Gb,可以快速填满服务器上的磁盘空间。我建议改为设置一个常量以将文件上传限制为更合理的值,例如在 Startup.cs 中

    using MyNamespace.Constants;
    public void ConfigureServices(IServiceCollection services)
    {
            ... other stuff
            services.Configure<FormOptions>(options => {
                options.MultipartBodyLengthLimit = Files.MaxFileUploadSizeKiloBytes;
            })
     }
    

    并且在一个单独的常量类中:

    namespace MyNamespace.Constants
    {
        public static class Files
        {
            public const int MaxFileUploadSizeKiloBytes = 250000000; // max length for body of any file uploaded
        }
    }
    

    【讨论】:

      【解决方案4】:

      如果有人仍然面临这个问题,我创建了一个中间件来拦截请求并创建另一个主体

          public class FileStreamUploadMiddleware
          {
              private readonly RequestDelegate _next;
      
              public FileStreamUploadMiddleware(RequestDelegate next)
              {
                  _next = next;
              }
      
              public async Task Invoke(HttpContext context)
              {
                  if (context.Request.ContentType != null)
                  {
                      if (context.Request.Headers.Any(x => x.Key == "Content-Disposition"))
                      {
                          var v = ContentDispositionHeaderValue.Parse(
                              new StringSegment(context.Request.Headers.First(x => x.Key == "Content-Disposition").Value));
                          if (HasFileContentDisposition(v))
                          {
                              using (var memoryStream = new MemoryStream())
                              {
                                  context.Request.Body.CopyTo(memoryStream);
                                  var length = memoryStream.Length;
                                  var formCollection = context.Request.Form =
                                      new FormCollection(new Dictionary<string, StringValues>(),
                                          new FormFileCollection()
                                              {new FormFile(memoryStream, 0, length, v.Name.Value, v.FileName.Value)});
                              }
                          }
                      }
                  }
      
                  await _next.Invoke(context);
              }
      
              private static bool HasFileContentDisposition(ContentDispositionHeaderValue contentDisposition)
              {
                  // this part of code from  https://github.com/aspnet/Mvc/issues/7019#issuecomment-341626892
                  return contentDisposition != null
                         && contentDisposition.DispositionType.Equals("form-data")
                         && (!string.IsNullOrEmpty(contentDisposition.FileName.Value)
                             || !string.IsNullOrEmpty(contentDisposition.FileNameStar.Value));
              }
          }
      

      在控制器中我们可以从请求中获取文件

              [HttpPost("/api/file")]
              public IActionResult GetFile([FromServices] IHttpContextAccessor contextAccessor,
                  [FromServices] IHostingEnvironment environment)
              {
                  //save the file
                  var files = Request.Form.Files;
                  foreach (var file in files)
                  {
                      var memoryStream = new MemoryStream();
                      file.CopyTo(memoryStream);
      
                      var fileStream = File.Create(
                          $"{environment.WebRootPath}/images/background/{file.FileName}", (int) file.Length,
                          FileOptions.None);
                      fileStream.Write(memoryStream.ToArray(), 0, (int) file.Length);
      
                      fileStream.Flush();
                      fileStream.Dispose();
      
                      memoryStream.Flush();
                      memoryStream.Dispose();
                  }
      
                  return Ok();
              }
      

      您可以根据需要改进代码,例如:在请求正文中添加表单参数并对其进行反序列化。

      我猜这是一种解决方法,但它可以完成工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-17
        • 2019-08-30
        • 1970-01-01
        • 2022-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-17
        相关资源
        最近更新 更多