ASP.NET Web API,使用 Flex FileReference 上传时出现 MIME 多部分流意外结束。

28

在 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;
}

通过标准的multipart HTML表单上传文件完全正常。但是,当另一个开发者尝试通过Flex的FileReference类构建的multipart表单上传文件时,会抛出错误:
意外的MIME多部分流结束。 MIME多部分消息不完整。
我不知道问题是出在Web API还是Flex上。我找到了一些相关的解决方法,但没有任何效果(使用ASP.Net Web API进行多部分表单POST),最近发现了这个(Webapi上传时出现“MIME多部分流。 MIME多部分消息不完整”错误)。如果第二个链接是正确的,那么有人知道它是否已经在通过Nuget可用的当前版本的Web API中发布了吗?该讨论是在5月份进行的,Nuget的最新版本是8月份,因此我认为此修复已经部署,并且不是我的问题的根本原因。

9
在已删除的答案中找到一个占位符,直到其中一个被恢复。我也遇到了同样的问题,解决方法很简单——在文件上传元素中添加名称。 <input name="FailsWithoutThis" type="file" />。太蠢了。 - user1228
1
没有名称,输入不会被发布。 - liammclennan
7个回答

37

我也在MVC4中遇到了同样的问题,但Will是正确的,给你的输入添加一个名称即可......

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

所有魔法都已恢复并正常运作!


就是这么简单。谢谢。 - Amanda

36

我也曾经遇到过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);
希望这有所帮助。

2
感谢您抽出时间发布这篇文章。 - leojh
2
到目前为止,我看到的唯一解决Flash POST问题的方法是创建一个虚拟流来检测内部流的结尾并附加CRLF。如果文件很大,这种方法很容易出错。 - georgiosd
1
谢谢!这对我真的有用(Adobe Air Mobile上传到WebApi 2.0)。这比一些疯狂的建议要简单得多。 - Marcus
4
我已经实现了这个,但仍然出现错误。还有什么想法吗? - The Dumb Radish
2
@TheDumbRadish 如果你在添加了这段代码后仍然遇到同样的问题,那么你的流可能不在开头。在第一行代码之后添加以下内容:reqStream.Position = 0; - Peter
显示剩余2条评论

10

阅读您现有的研究并跟踪到报告的codeplex问题,似乎有人在9月份确认此问题仍然存在。

他们认为MVC 4无法解析没有终止"\r\n"的上传文件。

问题非常简单,但是难以修复。问题在于Uploadify没有在MultiPartForm消息的末尾添加"\r\n"

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

检查Flex上传是否添加了"\r\n"可能是值得的。


不确定 Flex 是否有其他类型的上传方式,但 Flash 的 FileReference.upload() 并不会添加它。我认为这就是 Uploadify 也不添加它的原因,因为它们无法真正地改变默认行为。 - jayarjo

10
对于那些搜索此处的人:

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

如果多次读取请求流也会导致这个异常。我苦恼了几个小时,直到我找到一个来源解释说请求流只能被读取一次。
在我的情况下,我尝试使用 MultipartMemoryStreamProvider 读取请求流,并同时让 ASP.NET 为我做一些魔法,通过指定(来自请求体的)参数来调用我的 api 方法。

你有找到任何解決此問題的方案嗎?有什麼可行的解決方法嗎? - Tobias Moe Thorstensen
1
@TobiasMoeThorstensen 目前唯一可用的解决方法是仅读取流一次(这并不是真正的解决方法)。您可以选择只使用MultiPartMemoryStreamProvider或使用[FromBody]让WebApi为您提取/解析值。我们最终完全依赖MultiPartMemoryStreamProvider来实现我们想要达到的目标。 - Niklas Källander
谢谢你!@NiklasKällander - Johny

4

请确保虚拟目录(以下示例中的“~/App_Data”目录)已经存在,其中图片文件首先被上传。在发布项目时,它可能不会包含在输出文件中。

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

1

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


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接