WebAPI无法parsing多部分/表单数据文章

我试图接受来自客户端(iOS应用程序)的文章,我的代码在阅读stream时一直失败。 说消息不完整。 我一直试图让这个工作几个小时,似乎是我的消息格式或东西是错误的。 所有我想要做的是读取一个string,但我正在与谁在做iOS部分的开发人员只知道如何发送multipart / form-data而不是content-type json。

这是确切的错误:

意外的MIME多部分stream结束。 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); } } 

我的应用程序也定期遇到这个错误。 升级到WEB API 2.1没有做任何事情,exception消息是完全无用的。

我觉得实际上发生了什么,但是在大文件上却令人窒息。 在web.config中增加我的最大请求限制似乎解决了它的权利。

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

(这将天花板设置为30米,将其设置为任何您需要的。

我也遇到过这个错误。 InnerExceptionCannot access a disposed object. 这意味着在您调用ReadAsMultipartAsync之前,某些内容正在读取您的stream。
在调用Request.Content.ReadAsMultipartAsync(provider)之前的某个地方,可以调用Request.Content.LoadIntoBufferAsync().Wait() ,它会将这个stream加载到一个缓冲区中,并允许您多次读取它。
这不是一个最佳的解决scheme,但它的工作原理。

我离开这里,因为我花了相当一段时间尝试其他解决方法,直到我碰到以下有用的答案,并有一些人有这个问题可能最终在这个职位。

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

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

 await Request.Content.ReadAsMultipartAsync(provider); 

您将需要:

  1. 将请求stream加载到内存

  2. 附加所需的\ r \ nstring

  3. 从内存内容创build一个stream内容

  4. 手动将请求标头添加到stream内容

  5. 最后用这个代替:

     streamContent.ReadAsMultipartAsync(provider); 

在这里查看Landuber Kassa的答案以获得完整的代码: ASP.NET Web API,从Flex FileReference上传时MIME多部分stream的意外结束

如果有人想使用它,只需修改Shaw Levin的答案即可。

boundary = value.Substring(0, value.IndexOf("\r\n")); 会发现CRLF的第一个出现,你应该改变它为boundary = value.Substring(0, value.LastIndexOf("\r\n")); 所以它寻找最后的发生。 否则,如果内容中包含CRLF,则会丢失请求中的部分数据。

有类似的错误的post,对于一些,解决scheme的工作是:提到Id =“”,名称=“”属性file uploadHTML控制,感谢WebAPI上传错误。 预期结束的MIME多部分stream。 MIME多部分邮件不完整

但在我的情况下,它没有解决上面的简单调整:(

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

有人问,所以这里是我的自定义分析器一直工作正常:

边界来自这里:

  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")); 

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

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