ASP.NET Web API,从 Flex FileReference 上传时 MIME 多部分流意外结束

Posted

技术标签:

【中文标题】ASP.NET Web API,从 Flex FileReference 上传时 MIME 多部分流意外结束【英文标题】:ASP.NET Web API, unexpected end of MIME multi-part stream when uploading from Flex FileReference 【发布时间】:2012-11-26 01:42:21 【问题描述】:

按照在 ASP.NET 上找到的教程,实现了一个 Web API 控制器方法来进行异步文件上传,如下所示:

public Task<HttpResponseMessage> PostFormData()

    // Check if the request contains multipart/form-data.
    if (!Request.Content.IsMimeMultipartContent())
    
        throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
    

    string root = HttpContext.Current.Server.MapPath("~/App_Data");
    var provider = new MultipartFormDataStreamProvider(root);

    // Read the form data and return an async task.
    var task = Request.Content.ReadAsMultipartAsync(provider).
        ContinueWith<HttpResponseMessage>(t =>
        
            if (t.IsFaulted || t.IsCanceled)
            
                Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);
            

            return Request.CreateResponse(HttpStatusCode.OK);
        );

    return task;

通过标准的多部分 html 表单上传文件非常有效。但是,当其他开发者尝试通过 Flex 的 FileReference 类构造的 multipart 表单上传文件时,会抛出错误:

MIME 多部分流意外结束。 MIME 多部分消息不完整。

我不知道问题出在 Web API 还是 Flex。我发现了一些没有影响的相关修复(Multipart form POST using ASP.Net Web API),最近又找到了这个("MIME multipart stream. MIME multipart message is not complete" error on webapi upload)。如果第二个链接成立,有谁知道它是否在通过 Nuget 提供的当前 Web API 版本中?讨论是在 5 月进行的,Nuget 的最新版本是 8 月,所以我认为这个修复程序已经部署,并且不是我的问题的根本原因。

【问题讨论】:

在此处放置一个占位符,直到其中一个已删除的答案被取消删除。我遇到了同样的问题,解决方法很简单——为文件上传元素添加一个名称。 &lt;input name="FailsWithoutThis" type="file" /&gt;。白痴。 如果没有名称,则不会发布输入。 【参考方案1】:

我在使用 MVC4 时遇到了同样的问题,但 Will 是正确的,在您的输入中添加一个名称.....

<input type="file" id="fileInput" name="fileInput"/>

所有的魔法都恢复正常了!

【讨论】:

就这么简单。谢谢【参考方案2】:

我在使用 flex 时遇到了同样的问题。下面是解决它的代码。基本上,我使用自定义流来附加 asp.net web api 所期望的换行符。

        Stream reqStream = Request.Content.ReadAsStreamAsync().Result;
        MemoryStream tempStream = new MemoryStream();
        reqStream.CopyTo(tempStream);



        tempStream.Seek(0, SeekOrigin.End);
        StreamWriter writer = new StreamWriter(tempStream);
        writer.WriteLine();
        writer.Flush();
        tempStream.Position = 0;


         StreamContent streamContent = new StreamContent(tempStream);
         foreach(var header in Request.Content.Headers)
         
             streamContent.Headers.Add(header.Key, header.Value);
         

        // Read the form data and return an async task.
         await streamContent.ReadAsMultipartAsync(provider);

希望这会有所帮助。

【讨论】:

感谢您抽出宝贵时间发布此内容 目前为止我看到的唯一解决方法是用于 Flash POST。如果它创建一个检测到内部流结束并附加 CRLF 的虚拟流,效率会更高。如果文件很大,这很容易爆炸。 谢谢!这实际上对我有用(Adobe Air Mobile 上传到 WebApi 2.0)。这比那里建议的一些疯狂的东西要简单得多。 我已经实现了这个,但仍然得到错误。还有什么想法吗? @TheDumbRadish 如果您在添加此代码后仍然遇到同样的问题,那么您的流可能不是在开始。在第一行代码后添加:reqStream.Position = 0;【参考方案3】:

通读您现有的研究并跟进报告的 codeplex 问题,看起来其他人确认此问题在 9 月仍然存在。

他们认为 MVC 4 无法在没有终止“\r\n”的情况下解析上传。

这个问题非常简单,但很难解决。问题是 Uploadify 没有在 MultiPartForm 消息的末尾添加“\r\n”

http://aspnetwebstack.codeplex.com/discussions/354215

检查一下 Flex 上传是否添加了“\r\n”

【讨论】:

不确定 Flex(是否有其他类型的上传?),但 Flash 的 FileReference.upload() 没有添加它。我认为这就是 Uploadify 没有添加它的原因,因为它们不能真正改变默认行为。【参考方案4】:

对于那些登陆这里谷歌搜索的人:

MIME 多部分流意外结束。 MIME 多部分消息不完整。

多次读取请求流也会导致此异常。我挣扎了好几个小时,直到找到一个解释请求流只能读取一次的来源。

在我的例子中,我结合尝试使用MultipartMemoryStreamProvider 读取请求流,同时让 ASP.NET 通过为我的 api 方法指定参数(来自请求正文)为我做一些魔术。

【讨论】:

您找到解决此问题的方法了吗?有什么解决方法吗? @TobiasMoeThorstensen 唯一可用的解决方法是只读取一次流(这不是真正的解决方法)。您要么只使用 MultiPartMemoryStreamProvider,要么使用 [FromBody] 让 WebApi 为您提取/解析值。我们最终完全依赖 MultiPartMemoryStreamProvider 来提供我们的解决方案,因为它更适合我们想要实现的目标。 谢谢你! @NiklasKällander【参考方案5】:

确保首先上传图像文件的虚拟目录(“~/App_Data”目录,如下例)是物理存在的。当您发布项目时,它可能不在输出文件中。

string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);

【讨论】:

【参考方案6】:

我刚刚删除了我在 post 方法中设置的标题,最终解决了这个问题。

【讨论】:

【参考方案7】:

问题出在这一行:

string root = HttpContext.Current.Server.MapPath("~/App_Data");

它只能在 localhost 中工作,您可以在 System.Web 对象(如 HttpContext.Current)不可用的任何上下文中使用 HostingEnvironment.MapPath 代替(例如,也来自静态方法)。

var mappedPath = System.Web.Hosting.HostingEnvironment.MapPath("~/SomePath");

另见What is the difference between Server.MapPath and HostingEnvironment.MapPath?

参考这个答案How to do a Server Map Path.

【讨论】:

以上是关于ASP.NET Web API,从 Flex FileReference 上传时 MIME 多部分流意外结束的主要内容,如果未能解决你的问题,请参考以下文章

将文件从 ASP.NET Core Web api 发布到另一个 ASP.NET Core Web api

如何从 ASP.NET MVC 到 ASP.NET Core Web API 的 PUT?

如何从 ASP.NET 核心 mvc 向 asp.net 核心中的 Web API 发出 PUT 请求?

如何从 ASP.net 5 web api 返回文件

从 ASP.NET Web API ASP.NET Core 2 返回 HTML 并获取 http 状态 406

从 asp.net web api 发布操作重定向