28

Following the tutorial found on ASP.NET, implemented a Web API controller method for doing asynchronous file uploads that looks like this:

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

Uploading a file via a standard multipart HTML form works perfectly. However, when another developer attempts to upload a file via multipart form constructed by Flex's FileReference class, an error is thrown:

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

I have no idea if the problem lies in Web API or Flex. I've found some sort of related fixes that had no affect (Multipart form POST using ASP.Net Web API), and more recently this one ("MIME multipart stream. MIME multipart message is not complete" error on webapi upload). If the second link holds true, does anyone know if it's out in the current release of Web API available via Nuget? The discussion was in May, the most recent release from Nuget was August, so I assume this fix was deployed already, and is not the root cause of my issue.

Community
  • 1
  • 1
intrepidus
  • 974
  • 2
  • 12
  • 24
  • 9
    Putting a placeholder here until one of the deleted answers gets undeleted. I had the same issue and the fix was simple--add a name to the file upload element. ``. Idiotic. –  Aug 12 '13 at 19:05
  • 1
    Without a name the input is not posted. – liammclennan Dec 10 '14 at 00:18

7 Answers7

37

I had the same problem with MVC4, but Will is correct, add a name to your input.....

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

and all the magic is back up and working!

Greg Sipes
  • 683
  • 6
  • 16
36

I had the same problem with flex. And below is the code that solved it. Basically I used a custom stream to append the newline that asp.net web api is expecting.

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

Hope this helps.

Landuber Kassa
  • 386
  • 3
  • 5
  • 2
    Thank you for taking the time to post this – leojh Aug 23 '13 at 21:46
  • 2
    Only workaround I've seen so far, for Flash POSTs. Would be more efficient if it made a virtual stream that detected the end of the inner stream and append a CRLF. This will blow up pretty easily if the files are large. – georgiosd Nov 25 '13 at 13:10
  • This solves the same issue caused by uploads from AngularJS apps. – Iravanchi Feb 23 '15 at 07:52
  • 1
    Thank you! This actually worked for me (Adobe Air Mobile uploading to WebApi 2.0). This is much simpler than some of the crazy stuff being suggested out there. – Marcus Aug 17 '15 at 21:27
  • 4
    I have implemented this but still get the error. Any further thoughts? – The Dumb Radish Dec 07 '16 at 16:06
  • 2
    @TheDumbRadish If you're still having the same issue once you've added this code then your stream may not be at the start. Add this after the first line of code: `reqStream.Position = 0;` – Peter Apr 24 '18 at 10:37
  • Thanks, adding reqStream.Position = 0; did the trick. – Hardik Shah Mar 29 '21 at 20:23
10

Reading through your existing research and following through to the codeplex issue reported it looks like someone else confirmed this issue to still exist in September.

They believe that MVC 4 fails to parse uploads without a terminating "\r\n".

The issue is really simple but extremely hard to fix. The problem is that Uploadify does > not add an "\r\n" at the end of the MultiPartForm message

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

It may be worth checking that the Flex upload adds the "\r\n"

Mark Jones
  • 12,156
  • 2
  • 50
  • 62
  • Not sure about Flex (does it have some other kind of upload?), but Flash's FileReference.upload() doesn't add it. I think that's why Uploadify doesn't add it as well, since they can't really alter default behavior. – jayarjo Jun 14 '13 at 19:31
10

For those landing here googling:

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

Reading the request stream more than once will also cause this exception. I struggled with it for hours until I found a source explaining that the request stream only could be read once.

In my case, I combined trying to read the request stream using a MultipartMemoryStreamProvider and at the same time letting ASP.NET do some magic for me by specifying parameters (coming from the request body) for my api method.

  • Did you find any solution to this issue? Any workarounds? – Tobias Moe Thorstensen Jun 15 '18 at 09:01
  • 1
    @TobiasMoeThorstensen the only workaround available is to only read the stream once (which isn't really a workaround). Either you only use the MultiPartMemoryStreamProvider or you use [FromBody] to have WebApi extract/resolve values for you. We ended up relying solely on the MultiPartMemoryStreamProvider for our solution as it fit better for what we wanted to achieve. – Niklas Källander Jul 23 '18 at 11:30
  • Thank you for this! @NiklasKällander – Johny Oct 23 '18 at 15:28
4

Make sure the virtual directory ("~/App_Data" directory as below example) where the image files are first uploaded are physically existance. When you publish the project, it may not be in the output files.

string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
Renats Stozkovs
  • 2,549
  • 10
  • 22
  • 26
1

I just removed my headers I was setting on my post method which ended up solving this issue.

dk_french032
  • 638
  • 1
  • 7
  • 22
1

The problem is this line:

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

It will only work in localhost, you can use HostingEnvironment.MapPath instead in any context where System.Web objects like HttpContext.Current are not available (e.g also from a static method).

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

See also What is the difference between Server.MapPath and HostingEnvironment.MapPath?

Reference to this answer How to do a Server Map Path.

Luis Pardo
  • 11
  • 1