Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebAPI cannot parse multipart/form-data post

I'm trying to accept a post from a client (iOS app) and my code keeps failing on reading the stream. Says the message is not complete. I've been trying to get this working for hours it seems like something is wrong in my message format or something. All I'm trying to do is read a string but the developer I'm working with who is doing the iOS part only knows how to send multipart/form-data not content-type json.

Here is exact error:

Unexpected end of MIME multipart stream. MIME multipart message is not complete."

It fails here: await Request.Content.ReadAsMultipartAsync(provider);

Headers:

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

Body:

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

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

Here is the WebAPI code:

    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);
        }
    }
like image 465
Shaw Levin Avatar asked Jan 06 '14 03:01

Shaw Levin


2 Answers

My application was experiencing this error periodically too. Upgrading to WEB API 2.1 did nothing and the exception message is completely useless.

I think what was actually happening though is it was choking on large files. Increasing my max request limits in web.config seemed to fix it right up.

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

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

(This sets the ceiling to 30 megs. Set it to whatever you need. More info here)

like image 80
Matt J. Avatar answered Sep 21 '22 01:09

Matt J.


I encountered this error too. The InnerException is Cannot access a disposed object. This means that something is reading your stream before your call to ReadAsMultipartAsync.
Somewhere before this call Request.Content.ReadAsMultipartAsync(provider), you can call Request.Content.LoadIntoBufferAsync().Wait(), which will load this tream into a buffer and allow you to read it more than once.
This is not an optimal solution, but it works.

like image 12
Lev Dubinets Avatar answered Sep 21 '22 01:09

Lev Dubinets