Different ways of uploading files using Http based APIs- Part 1

In this series of blog posts, I’ll show you various ways in which we can accept files for upload using an HTTP based API. I’ll be using ASP.NET Web API framework for this but the concept is not specific to asp.net and applies to any Http based API.

How you develop a file upload  API can be influenced by the following factors related to how the API will be used.

  • Will the API be used for only uploading the files or both file along with related metadata
  • Will the API be used for browser based uploads or for system to system uploads.

 

Broadly there are four options (different content types) which can be used for uploading files using an Http POST request.

  1. Multipart/form-data
  2. application/json (with base64 encoded file)
  3. multipart/related
  4. Directly posting file content in the request body with content type as the MIME type of the file

Lets look at each of these options one by one.

Multipart/form-data upload

This is the option which we mostly use when we upload files from web browser while posting HTML forms .Although this is not restricted only to browser based uploads and can be used in other cases where form based data needs to be sent across HTTP e.g. spreadsheets ,pdf etc.

In this case, you make a POST request with content type as multipart/form-data. The raw request would look something like shown below.


POST https://localhost:44390/api/Upload/MultipartForm HTTP/1.1
Content-Type: multipart/form-data; boundary=--------------------------35791144331909754991791
Content-Length: 1953

—————————-357911443319097549917913
Content-Disposition: form-data; name=”CustomerId”

785469

—————————-357911443319097549917913
Content-Disposition: form-data; name=”CustomerName”

ABC Ltd.

—————————-357911443319097549917913
Content-Disposition: form-data; name=”File”; filename=”findings.txt”
Content-Type: text/plain

This is a text file.
—————————-357911443319097549917913–

This is a POST request where we are posting a form ( a set of key-value pairs) which are following

CustomerId : 785469

CustomerName : ABC Ltd

File: A text file named “findings.txt”

Although it is not necessary that we use multipart /form-data request for posting a file it is almost an overkill if we are using this kind of request for posting a set of key-value pairs. There are other better ways of doing that e.g. JSON or x-www-form-urlencoded.

The content of the request has a boundary field defined (in this case ‘=————————–35791144331909754991791’) and that boundary text is used to separate different parts of the body (hence ‘multipart’). Each part of the body consists of one key and value pair. In our case the last part has the key ‘File’ and the value is the entire file.For further reading on the specification refer this RFC page.

Example

Let’s see how to build an API which accepts a multipart/form-data request for uploading a file in asp.net core.

Below is how the Sample API code looks like.

[HttpPost]
[Route("FormDataUpload")]
public IActionResult FormDataUpload([FromForm]FileFormData formData)
{

// Check if the request contains multipart/form-data.
if(formData.File == null)
{
return new UnsupportedMediaTypeResult();
}
var fileExtension = MimeTypeMap.GetExtension(formData.File.ContentType);
using var stream = System.IO.File.Create(GetFilePath("FormDataUpload", formData.CustomerId, fileExtension, fileUploadPath));
formData.File.CopyToAsync(stream);
return Ok();
}

and the FileFormData class which is the input parameter for the action method.

public class FileFormData
{
public string CustomerId { get; set; }

public string CustomerName { get; set; }

public IFormFile File { get; set; }
}

The whole code is available here.

When you post a multipart/ form-data request the asp.net automatically binds the requested content based on the name of the keys and you as a developer do not require to do any special processing.

Below is how you would be posting a multipart/form-data  request (i.e. calling the API) from a client application (e.g. if you are not using Html forms )

static void PostMultipartFormData()
{
using var client = new HttpClient();
var values = new[]
{
new KeyValuePair<string,string>("CustomerId","123123"),
new KeyValuePair<string,string>("CustomerName","ABC Ltd."),
};
using var content = new MultipartFormDataContent();
foreach(var val in values)
{
content.Add(new StringContent(val.Value), val.Key);
}
var fileContent = new StreamContent(new FileStream(uploadFilePath, FileMode.Open));
fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(fileContentType);
fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data")
{
Name = "File",
FileName = "Text.txt"
};
content.Add(fileContent);
var requestUri = "/api/Upload/FormDataUpload";
client.BaseAddress = new Uri(apiBaseAddress);
var result = client.PostAsync(requestUri, content).Result;
Console.WriteLine($"Response : {result.StatusCode}");
}

I will not be explaining details of asp.net core API development or concept of streams in .net in these posts .You can refer the MSDN documentation or these pluralsight courses (asp.net core & streams ) for knowing more about it.

In the next post, I’ll discuss how to post the file as part of JSON content.

5 thoughts on “Different ways of uploading files using Http based APIs- Part 1

  1. Pingback: Different ways of uploading files using Http based APIs- Part 2 | Coding Canvas

  2. Pingback: Different ways of uploading files using Http based APIs- Part 3 | Coding Canvas

  3. Imran

    Definitely helpful! Took a long time to find code that explains it well!

  4. Andrea Vincenzo Natale

    Dio ti benedica! Lavoro fantastico!

  5. Devtron

    What is the value of ‘fileContentType’ ?? Is it important to set Content-Type for each file when using the “Multipart/form-data” approach ?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.