Skip to main content

Handling Files

ASP.NET Web APIs are able to accept and return files. This page explains how this can be achieved.

Handling files in a request

Accepting files via an ASP.NET Web API can be done via a form-data upload. This is the most popular/well-known upload method formatting the data you send as a set of key/value pairs.

You normally need to specify Content-Type to multipart/form-data in the request, and then use [FromForm] attribute in MVC to bind values to variables (not actually explicitly necessary). Also, you can use the built-in IFormFile class to access the file uploaded:

[HttpPost]
public async Task<IActionResult> PostFormData([FromForm] IFormFile file)
{
// Validate the input. Put a limit on filesize to avoid large upload attacks.
// Only accept .pdf files (check content type)
if(file.Length == 0 ||file.Length > 20_971_520 || file.ContentType != "application/pdf")
{
return BadRequest("No file or an invalid one has been uploaded.");
}

var pathToFile = Path.Combine(Directory.GetCurrentDirectory(), $"uploaded_file_{Guid.NewGuid()}.pdf");

using (var fileStream = new FileStream(pathToFile, FileMode.Create))
{
file.CopyTo(fileStream);
}

// Created can also be returned of course
return Ok("Your file has been uploaded successfully.");
}

Handling files as a response

Returning files in a response is also possible and can be achieved as follows:

[Route("api/files")]
[ApiController]
public class FilesController : ControllerBase
{
private readonly FileExtensionContentTypeProvider _fileExtensionContentTypeProvider;

public FilesController(FileExtensionContentTypeProvider fileExtensionContentTypeProvider)
{
_fileExtensionContentTypeProvider = fileExtensionContentTypeProvider
?? throw new System.ArgumentNullException(nameof(fileExtensionContentTypeProvider));
}

[HttpGet("{fileId}")]
public ActionResult GetFile(string fileId)
{
var pathToFile = "someFilePath.pdf";

// check whether the file exists
if (!System.IO.File.Exists(pathToFile)) return NotFound();

if(!_fileExtensionContentTypeProvider.TryGetContentType(pathToFile, out var contentType))
{
// fallback/default value
contentType = "application/octet-stream";
}

var bytes = System.IO.File.ReadAllBytes(pathToFile);
return File(bytes, contentType, Path.GetFileName(pathToFile));
}
}

We used the FileExtensionContentTypeProvider here which needs to be registered first:

builder.Services.AddSingleton<FileExtensionContentTypeProvider>();