多部分正文长度限制超出异常

Posted

技术标签:

【中文标题】多部分正文长度限制超出异常【英文标题】: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:我已经解决了这个问题,请检查我自己的答案。 【参考方案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();
        

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

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

【讨论】:

以上是关于多部分正文长度限制超出异常的主要内容,如果未能解决你的问题,请参考以下文章

SQL的语句最大长度限制多少字符

解决JSON字符长度超出限制

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

MVC中JSON字符长度超出限制

ASPP.NET CORE WEBAPI:文件上传错误:System.IO.InvalidDataException:超过多部分正文长度限制 16384

Symfony HttpClient Stream 和 chunk->getContent() 超出正文大小限制