47

All the documentation / tutorials / questions about processing a file uploaded using FormData to a ASP.NET WebAPI handler use MultipartFormDataStreamProvider to process the multipart stream to split it into the relevant form fields and files.

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

await Request.Content.ReadAsMultipartAsync(provider);

foreach (MultipartFileData file in provider.FileData)
{
   // File
}

However, the files are automatically written to a directory during processsing.

It seems a lot of hassle when I could just use HttpContext.Current.Request.Files[0].InputStream to access a given file stream directly in memory.

How can WebAPI just access the file stream directly without the IO overhead of using MultipartFormDataStreamProvider?

Official tutorial: http://www.asp.net/web-api/overview/advanced/sending-html-form-data,-part-2

simbolo
  • 7,279
  • 6
  • 56
  • 96
  • 1
    I think [This Question](http://stackoverflow.com/questions/19723064/webapi-formdata-upload-to-db-with-extra-parameters) should answer your needs. – Jon Susiak Jan 16 '15 at 10:58
  • Thanks @JonSusiak - I wish I found that a few hours ago, I ended up doing the exact same thing by examining the source code or `MultipartFormDataStreamProvider` and using the `MultipartStreamProvider` provider to give me the file upload in a `MemoryStream` rather than writing it to disk. Was just getting round to posting the answer. – simbolo Jan 16 '15 at 11:33
  • @simbolo - why **didn't** you use `HttpContext.Current.Request.Files[0].InputStream`? Could you explain the disadvantage? – Merenzo Jan 24 '17 at 08:22
  • Microsoft has a really good example for how to upload files: https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part-2 – xdiegom Apr 23 '18 at 20:50
  • @Merenzo Compiler Error CS1061, 'HttpRequestMessage' does not contain a definition for 'Files' and no accessible extension method 'Files' accepting a first argument of type 'HttpRequestMessage' could be found. – lexeme Apr 30 '23 at 21:28

1 Answers1

90

Solved:

Use the existing simple MultipartMemoryStreamProvider. No custom classes or providers required. This differers from the duplicate question which solved the solution by writing a custom provider.

Then use it in a WebAPI handler as so:

public async Task<IHttpActionResult> UploadFile()
{
    if (!Request.Content.IsMimeMultipartContent())
    {
        return StatusCode(HttpStatusCode.UnsupportedMediaType);
    }        
  
    var filesReadToProvider = await Request.Content.ReadAsMultipartAsync();
    
    foreach (var stream in filesReadToProvider.Contents)
    {
        var fileBytes = await stream.ReadAsByteArrayAsync();
    }
    return StatusCode(HttpStatusCode.OK);
}
Schalk Versteeg
  • 1,057
  • 13
  • 23
simbolo
  • 7,279
  • 6
  • 56
  • 96
  • Where can I find IHttpActionResult ? – guiomie Jul 03 '15 at 19:49
  • @guiomie simple google: https://msdn.microsoft.com/en-us/library/system.web.http.ihttpactionresult(v=vs.118).aspx – simbolo Aug 10 '15 at 13:48
  • 1
    Could this code please be updated so that it compiles? Not all code paths return a value. Thanks. – mbx-mbx Sep 27 '17 at 12:42
  • 5
    @Magrangs - you simply need to return a Http Result such as return Ok(); – George Harnwell Oct 03 '17 at 11:44
  • end the method with: return Request.CreateResponse(HttpStatusCode.OK); – Henrik Høyer Jan 27 '18 at 14:20
  • Can I simply send even big files to this function, or I need to define some `boundary` and other fancy stuff in the client side which sends the file? – Unbreakable Feb 13 '19 at 06:45
  • This doesn't work though - it gets screwed up from an encoding perspective – A X Oct 07 '19 at 15:32
  • With asp.net 4.7 I am still getting exception Exception. Exception type full name: System.NullReferenceException.] - [System.NullReferenceException: Object reference not set to an instance of an object – David Oct 11 '19 at 00:49
  • Hi @simbolo, I am also wanting to do this and have managed to extract the file data using your approach. I also have additional form data as well though. Do you have any ideas how I can get to that? The filestoreadprovider is a collection of HttpContent objects, which I have managed to make into a list and walk through, but I cant seem to get at the data. Any Ideas? (Before I throw this out as seperate question..) Thanks... – Brett JB Oct 12 '19 at 09:38
  • 1
    The `MultipartMemoryStreamProvider` doesn't have an API for accessing form data that is included in the request like `MultipartFormDataStreamProvider.FormData` does. – Brent Woodle Nov 20 '19 at 16:26