Stream 意外结束,内容可能已被另一个组件读取。 Microsoft.AspNetCore.WebUtilities.MultipartReaderStream

Posted

技术标签:

【中文标题】Stream 意外结束,内容可能已被另一个组件读取。 Microsoft.AspNetCore.WebUtilities.MultipartReaderStream【英文标题】:Unexpected end of Stream, the content may have already been read by another component. Microsoft.AspNetCore.WebUtilities.MultipartReaderStream 【发布时间】:2018-09-26 18:50:57 【问题描述】:

当我尝试从请求中读取多部分内容时出现异常,提示该内容可能已被另一个组件读取。

 if (MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
            
                // Used to accumulate all the form url encoded key value pairs in the 
                // request.
                var formAccumulator = new KeyValueAccumulator();

                var boundary = Request.GetMultipartBoundary();
                var reader = new MultipartReader(boundary, HttpContext.Request.Body);
                var section = await reader.ReadNextSectionAsync();
                while (section != null)
                
                    ContentDispositionHeaderValue contentDisposition;
                    var hasContentDispositionHeader =
                        ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);
                
            

【问题讨论】:

【参考方案1】:

asp.net core 3 中,您必须将factories.RemoveType<FormFileValueProviderFactory>(); 添加到您的DisableFormValueModelBindingAttribute 属性中。

代码

[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)
    
    

Documentation

【讨论】:

这个答案很有用,并且在我将 DotNet 核心从 2.2 迁移到 3.1 时帮助了我。我的 API 在添加 FormFileValueProviderFactory 后工作。谢谢:)【参考方案2】:

原来我必须使用下面的属性来禁用表单值模型绑定。

[HttpPost]
    [Route("")]
    [DisableFormValueModelBinding]
    public async Task<IActionResult> Post()

属性实现如下

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter

    public void OnResourceExecuting(ResourceExecutingContext context)
    
        var factories = context.ValueProviderFactories;
        factories.RemoveType<FormValueProviderFactory>();
        factories.RemoveType<JQueryFormValueProviderFactory>();
    

    public void OnResourceExecuted(ResourceExecutedContext context)
    
    

【讨论】:

我喜欢使用 ValueProviderFactories.RemoveType&lt;T&gt;() 禁用每个工厂,但它仍然给我意外错误 是的,为我解决了。这是因为DisableFormValueModelBinding 自定义过滤器允许我们阻止该方法尝试自动绑定和验证输入,这会抢先读取输入流。这允许我们稍后使用MultipartReader 来解析request.Body。有用的参考; blog.bitscry.com/2018/03/12/… 这个答案帮助我解决了一个问题,即我尝试使用带有UploadFilesAsync(String cst, String data, String device) 的绑定,然后多部分会由于被绑定抢占而引发异常。现在它按预期工作。谢谢! 我们如何在中间件 startup.cs 类中禁用DisableFormValueModelBinding。在 .net core 2.2 中工作?【参考方案3】:

在我的具体情况下,我使用的是 MultipartReader 解析的有效负载中不存在的多部分边界值:

// multipartBoundary is not in the contents of httpResponseContentStream.
var multipartBoundary = "batchresponse_63d0e4c7-4d49-4961-a294-3902d1730c44";
var multipartReader = new MultipartReader(multipartBoundary, httpResponseContentStream);
// Unexpected end-of-stream error used to occur here:
var multipartSection = await multipartReader.ReadNextSectionAsync(cancellationToken);

更新 multipartBoundary 以反映正在解析的内容中存在的实际边界值后,代码就会按预期工作。

【讨论】:

【参考方案4】:

This 为我的 netcore 3.1 工作

你需要添加

factories.RemoveType<FormFileValueProviderFactory>();

关于这个方法

[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)
    
    

【讨论】:

此答案与@learner 答案有何不同?【参考方案5】:

我用[DisableFormValueModelBinding]还是报错,那我也用:

if (Request.ContentLength == 0)
                return BadRequest();

【讨论】:

【参考方案6】:

以防万一其他人就这个错误追鬼: 使用 net5 web api 我有一个控制器

    [HttpPost]
    [Route("api/fileupload/reportId")]
    [ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
    public async Task<IActionResult> FileUpload(int reportId)

这不是一个好主意。它给出了上面提到的错误,我记得必须通过文件属性传递额外的数据。这为我解决了它。只是为了完整性。这很正常

    [HttpPost]
    [Route("api/fileupload")]
    [ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
    public async Task<IActionResult> FileUpload()

【讨论】:

【参考方案7】:

Microsoft.AspNetCore.App 2.1.4 中有关于此的错误。我将此包更新为2.1.12 版本并解决了。

【讨论】:

能否提供此问题的参考资料?【参考方案8】:

就我而言,这是“邮递员”问题。我将文件发送到 REST 端点。在某些时候我开始收到此错误,但代码没有更改。

我在“邮递员”中再次重新选择了这个文件,一切正常。

【讨论】:

以上是关于Stream 意外结束,内容可能已被另一个组件读取。 Microsoft.AspNetCore.WebUtilities.MultipartReaderStream的主要内容,如果未能解决你的问题,请参考以下文章

有效模板上非常不直观的“意外结束标签”错误

StaleObjectStateException:行已被另一个事务更新或删除?

获取“SqlParameter 已被另一个 SqlParameterCollection 包含。”使用 SqlQuery 命令时出错

无法删除密钥。要删除的键已被另一个并发会话从索引中删除

gcloud cli 无法创建项目 - 您指定的项目 ID 已被另一个项目使用

C语言文件读取fscanf(),该怎么处理