【问题标题】:WebAPI cannot parse multipart/form-data postWebAPI 无法解析多部分/表单数据帖子
【发布时间】:2014-01-23 10:10:51
【问题描述】:

我正在尝试接受来自客户端(iOS 应用)的帖子,但我的代码在读取流时一直失败。说消息不完整。我一直试图让这个工作好几个小时,我的消息格式或其他东西似乎有问题。我要做的只是读取一个字符串,但与我一起做 iOS 部分的开发人员只知道如何发送 multipart/form-data 而不是 content-type json。

这是确切的错误:

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

这里失败了:await Request.Content.ReadAsMultipartAsync(provider);

标题:

POST http://localhost:8603/api/login HTTP/1.1
Host: localhost:8603
Accept-Encoding: gzip,deflate
Content-Type: multipart/form-data; boundary=------------nx-oauth216807
Content-Length: 364
Accept-Language: en-us
Accept: */*
Connection: keep-alive

主体:

--------------nx-oauth216807
Content-Disposition: form-data; name="token"

CAAH5su8bZC1IBAC3Qk4aztKzisZCd2Muc3no4BqVUycnZAFSKuleRU7V9uZCbc8DZCedYQTIFKwJbVZCANJCs4ZCZA654PgA22Nei9KiIMLsGbZBaNQugouuLNafNqIOTs9wDvD61ZA6WSTd73AVtFp9tQ1PmFGz601apUGHSimYZCjLfGBo40EBQ5z6eSMNiFeSylym1pK4PCvI17fXCmOcRix4cs96EBl8ZA1opGKVuWizOsS0WZCMiVGvT
--------------nx-oauth216807--

这里是 WebAPI 代码:

    public async Task<HttpResponseMessage> PostFormData()
    {
        // Check if the request contains multipart/form-data.
        if (!Request.Content.IsMimeMultipartContent())
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }
        try
        {
        string root = HttpContext.Current.Server.MapPath("~/App_Data");
        var provider = new MultipartFormDataStreamProvider(root);

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

        // This illustrates how to get the file names.
        foreach (MultipartFileData file in provider.FileData)
        {
            Trace.WriteLine(file.Headers.ContentDisposition.FileName);
            Trace.WriteLine("Server file path: " + file.LocalFileName);
        }
        return Request.CreateResponse(HttpStatusCode.OK);

        }
        catch (System.Exception e)
        {
            return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
        }
    }

【问题讨论】:

  • 5.0 及之前的 Web API 存在一个已知问题,即多部分表单数据请求末尾的额外行会导致 Web API 的多部分解析器出现问题。这个错误在 5.0 之后得到了修复。
  • 传入请求中的“额外行”在哪里?我可以尝试修复该请求。另外,您的意思是 .NET 5.0 吗?我正在使用 .NET 4.5。
  • 我的意思是最后一个边界之后的 CRLF..即--------------nx-oauth216807--
  • 我遇到了同样的错误“读取 MIME 多部分正文部分时出错。”有解决方法吗?还是 web api 2.1 还存在问题?
  • 我无法使用内置解析器来完成这项工作。我必须自己写。

标签: c# asp.net ios json asp.net-web-api


【解决方案1】:

我的应用程序也定期遇到此错误。升级到 WEB API 2.1 什么也没做,异常消息完全没用。

我认为实际发生的情况是大文件令人窒息。在 web.config 中增加我的最大请求限制似乎可以解决问题。

<system.web>
    <httpRuntime maxRequestLength="30000" />
</system.web>

<system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="30000" />
      </requestFiltering>
    </security>
</system.webServer>

(这将上限设​​置为 30 兆。将其设置为您需要的任何值。更多信息here

【讨论】:

  • 这实际上解决了这个问题。异常消息是错误的。谢谢!
  • &lt;httpRuntime maxRequestLength="30000000" /&gt; 中的 maxRequestLength 属性应以千字节为单位指定。 30MB 将是 30000。source
  • 我知道这是一个旧答案,但非常感谢。这解决了我已经研究了两个星期的问题。
  • 还设置 executionTimeout 并将调试设置为 false 可能会有所帮助。
【解决方案2】:

我也遇到了这个错误。 InnerExceptionCannot access a disposed object. 这意味着在您调用 ReadAsMultipartAsync 之前,有东西正在读取您的流。
在此呼叫Request.Content.ReadAsMultipartAsync(provider) 之前的某个地方,您可以拨打 Request.Content.LoadIntoBufferAsync().Wait(),这会将这个词组加载到缓冲区中,并允许您多次读取它。
这不是最佳解决方案,但它确实有效。

【讨论】:

  • 我间歇性地遇到一些图像文件的问题,而没有其他问题。不知道问题出在哪里,但效果很好 - 谢谢。
【解决方案3】:

我把这个留在这里,因为我花了很长时间尝试其他解决方法,直到我遇到了以下有用的答案,并且一些遇到这个问题的人可能会在这篇文章中结束。

需要在请求内容流的末尾附加一个\r\n。

而不是使用这一行来读取数据:

await Request.Content.ReadAsMultipartAsync(provider);

您需要:

  1. 将请求流加载到内存

  2. 附加所需的\r\n字符串

  3. 从内存内容创建流内容

  4. 手动将请求头添加到流内容中

  5. 最后改用这个:

    streamContent.ReadAsMultipartAsync(provider); 
    

在此处查看 Landuber Kassa 的答案以获取完整代码:ASP.NET Web API, unexpected end of MIME multi-part stream when uploading from Flex FileReference

【讨论】:

    【解决方案4】:

    只需修改 Shaw Levin 的答案,以防万一有人想使用它。

    boundary = value.Substring(0, value.IndexOf("\r\n")); 将查找 CRLF 的第一次出现,您应该将其更改为 boundary = value.Substring(0, value.LastIndexOf("\r\n")); 以便它查找最后一次出现。否则,如果内容在中间某处包含 CRLF,您将丢失请求中的部分数据。

    【讨论】:

      【解决方案5】:

      有类似的错误帖子,对于一些人来说,解决办法是:提到文件上传html控件的Id="",name=""属性,感谢WebAPI upload error. Expected end of MIME multipart stream. MIME multipart message is not complete

      但在我的情况下,它并没有通过上述简单的调整来解决:(

      【讨论】:

        【解决方案6】:

        我不会推荐这个答案 - 希望现在有更好的方法。

        有人问所以这是我的自定义解析器,它一直运行良好:

        边界来自这里:

                string value;
                using (var reader = new StreamReader(tempStream, Encoding.UTF8))
                {
                    value = reader.ReadToEnd();
                    // Do something with the value
                }
        
                boundary = value.Substring(0, value.IndexOf("\r\n"));
        

        然后我们在这里解析请求的内容:

           public Dictionary<string, BodyContent> ParseContent(string content)
            {
                string[] list = content.Split(new string[] { boundary }, StringSplitOptions.RemoveEmptyEntries);
                string name="", val="";
                Dictionary<string, BodyContent> temp = new Dictionary<string, BodyContent>();
                foreach (String s in list)
                {
                    if (s == "--" || s == "--\r\n")
                    {
                        //Do nothing.
                    }
                    else
                    {
                        string[] token = s.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                        val = "";
                        name = "";
                        foreach (string x in token)
                        {
        
                            if(x.StartsWith("Content-Disposition"))
                            {
                                //Name
                                name = x.Substring(x.IndexOf("name=")+5, x.Length - x.IndexOf("name=")-5);
                                name = name.Replace(@"\","");
                                name = name.Replace("\"","");
                            }
                            if (x.StartsWith("--"))
                            {
                                break;
                            }
                            if (!x.StartsWith("--") && !x.StartsWith("Content-Disposition"))
                            {
                                val = x;
                            }
        
                        }
                        if (name.Length > 0)
                        {
                            BodyContent b = new BodyContent();
                            b.content = name;
                            if (val.Length == 0)
                            {
                                b.value = "";
                            }
                            else
                            {
                                b.value = val;
                            }
                            temp.Add(name, b);
                        }
                    }
        
                }
                return temp;        
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-11-07
          • 2019-06-01
          • 2015-12-29
          • 2016-06-18
          • 1970-01-01
          • 2014-11-02
          • 2014-09-21
          • 2016-11-03
          相关资源
          最近更新 更多