In this article, I am going to disclose how to upload multipart/form-data, picture, pdf, excel, etc. to the server using Web API. Web API is essentially used as a mediator between client and server. It exposes the server side information to the client like (Website, Android, iPhone and etc.). The client can specifically communicate with the server using Web API. Web API exposes the server information as JSON.
Here, I will explain how to make a Web API to upload images, documents, PPT, multipart/form-data, etc. on Server, and save on local folder.
What is multipart/form-data?
enctype='multipart/form-data' means that is the type of content-type for which no characters will be encoded in content. That is why this type is used while uploading the files from client to server. So multipart/form-data is used when a form requires binary data in content, like the file document, etc.
Here, I will explain how to make a Web API to upload images, documents, PPT, multipart/form-data, etc. on Server, and save on local folder.
What is multipart/form-data?
enctype='multipart/form-data' means that is the type of content-type for which no characters will be encoded in content. That is why this type is used while uploading the files from client to server. So multipart/form-data is used when a form requires binary data in content, like the file document, etc.
To upload multipart/form-data using Web API, follow some simple steps as given below.
Step 1 - The first step is to create a new project with MVC Web API named as "UploadDocsDummy".


In this image, you can see that I have selected both checkboxes, "MVC" and "Web API. So, you can also select both or only "Web API". Now, click "OK"

Step 2 - Create an empty folder "ClientDocument" in your application to save document/image etc.You can see in the next image which is already created.

Step 2 - Create an empty folder "ClientDocument" in your application to save document/image etc.You can see in the next image which is already created.
Step 3 - Create a model class "InMemoryMultipartFormDataStreamProvider" inside Models folder and use this code. In this code, I am configuring multipart/form-data.
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Collections.Specialized;
- using System.IO;
- using System.Linq;
- using System.Net.Http;
- using System.Net.Http.Headers;
- using System.Threading.Tasks;
- using System.Web;
- namespace UploadDocsDummy.Models
- {
- public class InMemoryMultipartFormDataStreamProvider : MultipartStreamProvider
- {
- private NameValueCollection _formData = new NameValueCollection();
- private List<HttpContent> _fileContents = new List<HttpContent>();
- // Set of indexes of which HttpContents we designate as form data
- private Collection<bool> _isFormData = new Collection<bool>();
- /// <summary>
- /// Gets a <see cref="NameValueCollection"/> of form data passed as part of the multipart form data.
- /// </summary>
- public NameValueCollection FormData
- {
- get { return _formData; }
- }
- /// <summary>
- /// Gets list of <see cref="HttpContent"/>s which contain uploaded files as in-memory representation.
- /// </summary>
- public List<HttpContent> Files
- {
- get { return _fileContents; }
- }
- public override Stream GetStream(HttpContent parent, HttpContentHeaders headers)
- {
- // For form data, Content-Disposition header is a requirement
- ContentDispositionHeaderValue contentDisposition = headers.ContentDisposition;
- if (contentDisposition != null)
- {
- // We will post process this as form data
- _isFormData.Add(String.IsNullOrEmpty(contentDisposition.FileName));
- return new MemoryStream();
- }
- // If no Content-Disposition header was present.
- throw new InvalidOperationException(string.Format("Did not find required '{0}' header field in MIME multipart body part..", "Content-Disposition"));
- }
- /// <summary>
- /// Read the non-file contents as form data.
- /// </summary>
- /// <returns></returns>
- public override async Task ExecutePostProcessingAsync()
- {
- // Find instances of non-file HttpContents and read them asynchronously
- // to get the string content and then add that as form data
- for (int index = 0; index < Contents.Count; index++)
- {
- if (_isFormData[index])
- {
- HttpContent formContent = Contents[index];
- // Extract name from Content-Disposition header. We know from earlier that the header is present.
- ContentDispositionHeaderValue contentDisposition = formContent.Headers.ContentDisposition;
- string formFieldName = UnquoteToken(contentDisposition.Name) ?? String.Empty;
- // Read the contents as string data and add to form data
- string formFieldValue = await formContent.ReadAsStringAsync();
- FormData.Add(formFieldName, formFieldValue);
- }
- else
- {
- _fileContents.Add(Contents[index]);
- }
- }
- }
- /// <summary>
- /// Remove bounding quotes on a token if present
- /// </summary>
- /// <param name="token">Token to unquote.</param>
- /// <returns>Unquoted token.</returns>
- private static string UnquoteToken(string token)
- {
- if (String.IsNullOrWhiteSpace(token))
- {
- return token;
- }
- if (token.StartsWith("\"", StringComparison.Ordinal) && token.EndsWith("\"", StringComparison.Ordinal) && token.Length > 1)
- {
- return token.Substring(1, token.Length - 2);
- }
- return token;
- }
- }
- }
Step 4 - Create a new apiController "DocumentUploadController" inside Controllers folder.

Step 5 - If you have created a new Controller "DocumentUpload", then create a new API (Action) "MediaUpload" like this.
- using System;
- using System.Collections.Generic;
- using System.Collections.Specialized;
- using System.IO;
- using System.Linq;
- using System.Net;
- using System.Net.Http;
- using System.Threading.Tasks;
- using System.Web;
- using System.Web.Configuration;
- using System.Web.Http;
- using UploadDocsDummy.Models;
- namespace UploadDocsDummy.Controllers
- {
- public class DocumentUploadController : ApiController
- {
- /// <summary>
- /// Upload Document.....
- /// </summary>
- /// <returns></returns>
- [HttpPost]
- [Route("api/DocumentUpload/MediaUpload")]
- public async Task<HttpResponseMessage> MediaUpload()
- {
- // Check if the request contains multipart/form-data.
- if (!Request.Content.IsMimeMultipartContent())
- {
- throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
- }
- var provider = await Request.Content.ReadAsMultipartAsync<InMemoryMultipartFormDataStreamProvider>(new InMemoryMultipartFormDataStreamProvider());
- //access form data
- NameValueCollection formData = provider.FormData;
- //access files
- IList<HttpContent> files = provider.Files;
- HttpContent file1 = files[0];
- var thisFileName = file1.Headers.ContentDisposition.FileName.Trim('\"');
- ////-------------------------------------For testing----------------------------------
- //to append any text in filename.
- //var thisFileName = file1.Headers.ContentDisposition.FileName.Trim('\"') + DateTime.Now.ToString("yyyyMMddHHmmssfff"); //ToDo: Uncomment this after UAT as per Jeeevan
- //List<string> tempFileName = thisFileName.Split('.').ToList();
- //int counter = 0;
- //foreach (var f in tempFileName)
- //{
- // if (counter == 0)
- // thisFileName = f;
- // if (counter > 0)
- // {
- // thisFileName = thisFileName + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + "." + f;
- // }
- // counter++;
- //}
- ////-------------------------------------For testing----------------------------------
- string filename = String.Empty;
- Stream input = await file1.ReadAsStreamAsync();
- string directoryName = String.Empty;
- string URL = String.Empty;
- string tempDocUrl = WebConfigurationManager.AppSettings["DocsUrl"];
- if (formData["ClientDocs"] == "ClientDocs")
- {
- var path = HttpRuntime.AppDomainAppPath;
- directoryName = System.IO.Path.Combine(path, "ClientDocument");
- filename = System.IO.Path.Combine(directoryName, thisFileName);
- //Deletion exists file
- if (File.Exists(filename))
- {
- File.Delete(filename);
- }
- string DocsPath = tempDocUrl + "/" + "ClientDocument" + "/";
- URL = DocsPath + thisFileName;
- }
- //Directory.CreateDirectory(@directoryName);
- using (Stream file = File.OpenWrite(filename))
- {
- input.CopyTo(file);
- //close file
- file.Close();
- }
- var response = Request.CreateResponse(HttpStatusCode.OK);
- response.Headers.Add("DocsUrl", URL);
- return response;
- }
- }
- }
Step 6 - Now, we need to configure "DocsUrl" in web.config file. which are using in API code to get URL. Don't forget to configure this.
- <appSettings>
- <add key="DocsUrl" value="http://localhost:51356" />
- </appSettings>
As shown in the above image, I have created a key in web.config file along with Models and Controllers folder.
Step 7- Run the application and use Postman to test Web API. If you are not aware about Postman, click here, otherwise see in the image how to configure Postman to test Web API.

You will put your route and use form-data and post the value and image,document.in postman. After configuring all the things click on send and see out put like this -- see image.
In this image, we are returning the file URL in header. Image has been saved in "ClientDocument" Folder.

You will put your route and use form-data and post the value and image,document.in postman. After configuring all the things click on send and see out put like this -- see image.
In this image, we are returning the file URL in header. Image has been saved in "ClientDocument" Folder.
I hope you are good to post multipart/form-data. You can download this project which I've already done.


VAHID NPosted Mar 20, 2021, 6:05 AM
When i try to call api throug postman i getting an error like this. "ExceptionMessage": "Empty path name is not legal."
Mehmet KuzuPosted Dec 25, 2019, 1:07 PM
Have you any sample by using AJAX.. which is not sending any image file and WebApi 2throws 415 error.. formdata can not pass the serverside..
SandmangsPosted May 23, 2019, 11:45 AM
Thanks for the tutorial, it was helpful. As feedback, though, the images you provide are very low quality, and I had to research and determine how to use Postman for the testing as I couldn't read the images at all. Cheers!
kilesh nishadPosted Apr 22, 2019, 2:39 PM
Thanks sir, Its Best solution for me......
sharad chougalePosted Oct 2, 2018, 6:41 AM
I have find this issue Error 1 'UploadDocsDummy.Models.InMemoryMultipartFormDataStreamProvider.GetStream(System.Net.Http.HttpContent, System.Net.Http.Headers.HttpContentHeaders)': no suitable method found to override E:\Application\MultiPart API\6\UploadDocsDummy\UploadDocsDummy\Models\InMemoryMultipartFormDataStreamProvider.cs 38 32 UploadDocsDummyplease help me
sharad chougalePosted Oct 2, 2018, 5:54 AM
Can you share me multi-part API project on my mail id [email protected] because above project cant work my system.
George CokerPosted Jun 14, 2018, 12:05 AM
Hello Bikesh, my requirement is to call web api from a web application. Controls would be on web application and uploading a file from web application will call web api method to process the uploaded file with some other form variables like firstname, Lastname, email, etc
tarakPosted Sep 21, 2017, 12:44 AM
Hi Bikesh , I just need following conversion in WCF compliant code. var provider = await Request.Content.ReadAsMultipartAsync(new InMemoryMultipartFormDataStreamProvider());Can you please share code for only this one line ?
Paul VölkerPosted Sep 5, 2017, 6:28 AM
It worked, thank you Bikesh Srivastava. do you have the code for sending a POST with csharp aswell? i want to send it out of a mobile app (xamarin forms).
Paul VölkerPosted Sep 5, 2017, 4:02 AM
Hey, what is the second key at postman to test the api`?
Rajvir YadavPosted Aug 21, 2017, 12:39 PM
I want to upload multiple file from postman into web api use model so please suggest me how can i do.
Bikesh SrivastavaPosted Sep 26, 2016, 10:51 PM
Thnaks
Manav PandyaPosted Sep 25, 2016, 2:11 AM
Well explained sir ...Thanks , i much needed this one
Humayun Kabir MamunPosted Sep 25, 2016, 1:58 AM
Nice...