In this short tutorial, we are going to see how to upload multiple files using MultipartFormDataStreamProvider in ASP.Net WebAPI. The concept is based on Multipart/form-data in which we can POST not only multiple file contents but also regular form fields which will be available as NameValueCollection on server side.In this tutorial we also see how to override the default behavior of MultipartFormDataStreamProvider which stores the name in a unique BodyPart_{GUID} format to much more meaningful name. We will also invoke our WebAPI using Fiddler to POST file data. Alongside we develop a sample console application which will POST file data using HttpClient class.
Code is pretty much self-explanatory. Comments are provided at necessary points for better understandability.
ASP.Net Web API (Create a New Project, then create ApiControlller, please the following code in it)
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; using System.Web; using System.Web.Http; using System.Web.Mvc; namespace UploadApplication.Controllers { public class UploadController : ApiController { public async Task<HttpResponseMessage> Post() { // Check whether the POST operation is MultiPart? if (!Request.Content.IsMimeMultipartContent()) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } // Prepare CustomMultipartFormDataStreamProvider in which our multipart form // data will be loaded. string fileSaveLocation = HttpContext.Current.Server.MapPath("~/App_Data"); CustomMultipartFormDataStreamProvider provider = new CustomMultipartFormDataStreamProvider(fileSaveLocation); List<string> files = new List<string>(); try { // Read all contents of multipart message into CustomMultipartFormDataStreamProvider. await Request.Content.ReadAsMultipartAsync(provider); foreach (MultipartFileData file in provider.FileData) { files.Add(Path.GetFileName(file.LocalFileName)); } // Send OK Response along with saved file names to the client. return Request.CreateResponse(HttpStatusCode.OK, files); } catch (System.Exception e) { return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e); } } } // We implement MultipartFormDataStreamProvider to override the filename of File which // will be stored on server, or else the default name will be of the format like Body- // Part_{GUID}. In the following implementation we simply get the FileName from // ContentDisposition Header of the Request Body. public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider { public CustomMultipartFormDataStreamProvider(string path) : base(path) { } public override string GetLocalFileName(HttpContentHeaders headers) { return headers.ContentDisposition.FileName.Replace("\"", string.Empty); } } }
Testing using Fiddler –

Response –

Now lets create a simple Console application which will programmatically POST file contents to our above API –
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { using (var client = new HttpClient()) using (var content = new MultipartFormDataContent()) { // Make sure to change API address client.BaseAddress = new Uri("http://localhost:53798/"); // Add first file content var fileContent1 = new ByteArrayContent(File.ReadAllBytes(@"c:\Users\aisadmin\Desktop\Me\NF2202533167366.pdf")); fileContent1.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "Sample.pdf" }; // Add Second file content var fileContent2 = new ByteArrayContent(File.ReadAllBytes(@"c:\Users\aisadmin\Desktop\Sample.txt")); fileContent2.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "Sample.txt" }; content.Add(fileContent1); content.Add(fileContent2); // Make a call to Web API var result = client.PostAsync("/api/upload", content).Result; Console.WriteLine(result.StatusCode); Console.ReadLine(); } } } }
Output of above code can be examined by navigating to App_Data folder of the Web API –

Happy Coding!!!






Pingback: Blog Posts of the Week (14th - 20th July 2013) - The South Asia MVP Blog - Site Home - TechNet Blogs()