How to upload multipart/form-data to ASP.NET Core Web API?
Key scenarios
I am a user, having a class of objects with few properties and a file (pdf or image) whatever, to be sent to the server successfully - how do I get it done using Web API?
This article describes the step-by-step simple way of uploading class objects as JSON data and a file (pdf) to a server HTTP Post multipart/form-data.
ASP.NET Core supports uploading one or more files using buffered model binding for smaller files and unbuffered streaming for larger files.
What Software Tools used?
ASP.NET Core 2.0, Visual Studio 2017, Visual Studio 2019, Web API 2, and C# programming language console application.
Server - .NET Core Web API 2 application which stores the uploaded file
Client - C# Console application consumes server Web API Endpoint.
How a file pdf or image sent to a server?
Unlike the older version, .NET Core introduces an IFormFile Interface. It 'represents a file sent with the HttpRequest' and used namespacesMicrosoft.AspNetCore.Http
IFormFile helps to handle uploaded files with ease.
Using IFormFile in ASP.Net Core uploading multipart/form-data in HTTP Post is much easier.
So now let's see the real code practice of the client and the server.
It is better we complete server-side code first and then define client-side console code.
1. How the server stores the uploaded file?
Notice
For now you can ignore or comment out the custom attribute class implemented in the class attribute.
DemoData
public class DemoData
{
[Required(ErrorMessage = "Please input api key")]
[StringLength(500, ErrorMessage = "{0} cannot be greater than {1} characters.")]
[JsonProperty("apiKey")]
public string ApiKey { get; set; }
[Required(ErrorMessage = "Please input attachment type")]
[StringLength(4, ErrorMessage = "{0} cannot be greater than {1} characters.")]
[JsonProperty("attachmentType")]
public string AttachmentType { get; set; }
[StringLength(10, ErrorMessage = "{0} cannot be greater than {1} characters.")]
[JsonProperty("Sano")]
public string Sano { get; set; }
[Required(ErrorMessage = "Please upload pdf file")]
[JsonProperty("file")]
[CustomMaxFileSize(AppSettings.FILE_SIZE)] //(5 * 1024 * 1024) 5mb
[IFormFileValidation(AppSettings.PDF_EXT)] // .pdf
public IFormFile File { get; set; }
}
public class DemoData
{
[Required(ErrorMessage = "Please input api key")]
[StringLength(500, ErrorMessage = "{0} cannot be greater than {1} characters.")]
[JsonProperty("apiKey")]
public string ApiKey { get; set; }
[Required(ErrorMessage = "Please input attachment type")]
[StringLength(4, ErrorMessage = "{0} cannot be greater than {1} characters.")]
[JsonProperty("attachmentType")]
public string AttachmentType { get; set; }
[StringLength(10, ErrorMessage = "{0} cannot be greater than {1} characters.")]
[JsonProperty("Sano")]
public string Sano { get; set; }
[Required(ErrorMessage = "Please upload pdf file")]
[JsonProperty("file")]
[CustomMaxFileSize(AppSettings.FILE_SIZE)] //(5 * 1024 * 1024) 5mb
[IFormFileValidation(AppSettings.PDF_EXT)] // .pdf
public IFormFile File { get; set; }
}
TestARAttachmentController.cs
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Hosting;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Net.Http;
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
using System.Net.Http.Headers;
namespace Api.Controllers
{
public class TestARAttachmentController : ControllerBase
{
public static IHostingEnvironment _environment;
public TestARAttachmentController(IHostingEnvironment environment)
{
_environment = environment;
}
public class DemoData
{
[Required(ErrorMessage = "Please input api key")]
[StringLength(500, ErrorMessage = "{0} cannot be greater than {1} characters.")]
[JsonProperty("apiKey")]
public string ApiKey { get; set; }
[Required(ErrorMessage = "Please input attachment type")]
[StringLength(4, ErrorMessage = "{0} cannot be greater than {1} characters.")]
[JsonProperty("attachmentType")]
public string AttachmentType { get; set; }
[StringLength(10, ErrorMessage = "{0} cannot be greater than {1} characters.")]
[JsonProperty("sano")]
public string Sano { get; set; }
[Required(ErrorMessage = "Please upload pdf file")]
[JsonProperty("file")]
[CustomMaxFileSize(AppSettings.FILE_SIZE)]
[IFormFileValidation(AppSettings.PDF_EXT)]
public IFormFile File { get; set; }
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DemoFormDataUpload([FromForm] DemoData formData)
{
// Check if the request contains multipart/form-data.
if (formData.File == null)
{
return new UnsupportedMediaTypeResult();
}
if (formData.File.Length > 0)
{
IFormFile formFile = formData.File;
var folderPath = Path.Combine(_environment.WebRootPath, "upload");
//var filePath = Path.Combine(folderPath, $"{Path.GetRandomFileName() + Path.GetExtension(formFile.FileName).ToLowerInvariant()}");
var filePath = Path.Combine(folderPath, formFile.FileName);
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
await formFile.CopyToAsync(fileStream);
fileStream.Flush();
return Ok(new { status = "Upload Success", length = formFile.Length, name = formFile.FileName });
}
}
else
{
return NotFound("Failed to upload");
}
}
}
}
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Hosting;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Net.Http;
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
using System.Net.Http.Headers;
namespace Api.Controllers
{
public class TestARAttachmentController : ControllerBase
{
public static IHostingEnvironment _environment;
public TestARAttachmentController(IHostingEnvironment environment)
{
_environment = environment;
}
public class DemoData
{
[Required(ErrorMessage = "Please input api key")]
[StringLength(500, ErrorMessage = "{0} cannot be greater than {1} characters.")]
[JsonProperty("apiKey")]
public string ApiKey { get; set; }
[Required(ErrorMessage = "Please input attachment type")]
[StringLength(4, ErrorMessage = "{0} cannot be greater than {1} characters.")]
[JsonProperty("attachmentType")]
public string AttachmentType { get; set; }
[StringLength(10, ErrorMessage = "{0} cannot be greater than {1} characters.")]
[JsonProperty("sano")]
public string Sano { get; set; }
[Required(ErrorMessage = "Please upload pdf file")]
[JsonProperty("file")]
[CustomMaxFileSize(AppSettings.FILE_SIZE)]
[IFormFileValidation(AppSettings.PDF_EXT)]
public IFormFile File { get; set; }
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DemoFormDataUpload([FromForm] DemoData formData)
{
// Check if the request contains multipart/form-data.
if (formData.File == null)
{
return new UnsupportedMediaTypeResult();
}
if (formData.File.Length > 0)
{
IFormFile formFile = formData.File;
var folderPath = Path.Combine(_environment.WebRootPath, "upload");
//var filePath = Path.Combine(folderPath, $"{Path.GetRandomFileName() + Path.GetExtension(formFile.FileName).ToLowerInvariant()}");
var filePath = Path.Combine(folderPath, formFile.FileName);
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
await formFile.CopyToAsync(fileStream);
fileStream.Flush();
return Ok(new { status = "Upload Success", length = formFile.Length, name = formFile.FileName });
}
}
else
{
return NotFound("Failed to upload");
}
}
}
}
Download From Server
[HttpGet]
public PhysicalFileResult DownloadFile(string fileName)
{
return new PhysicalFileResult(Path.Combine(_environment.WebRootPath,"upload",fileName),"application/pdf");
}
[HttpGet]
public FileStreamResult DownloadFile1(string fileName)
{
var filePath = Path.Combine(_environment.WebRootPath, "upload", fileName);
var fileStream = new FileStream(filePath,FileMode.Open, FileAccess.Read);
return File(fileStream, "application/pdf", fileName);
}
[HttpGet]
public FileStreamResult DownloadFileStream(string fileName)
{
var filePath = Path.Combine(_environment.WebRootPath, "upload", fileName);
var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
return new FileStreamResult(fileStream,"application/pdf")
{
FileDownloadName = fileName
};
}
[HttpGet] public PhysicalFileResult DownloadFile(string fileName) { return new PhysicalFileResult(Path.Combine(_environment.WebRootPath,"upload",fileName),"application/pdf"); } [HttpGet] public FileStreamResult DownloadFile1(string fileName) { var filePath = Path.Combine(_environment.WebRootPath, "upload", fileName); var fileStream = new FileStream(filePath,FileMode.Open, FileAccess.Read); return File(fileStream, "application/pdf", fileName); } [HttpGet] public FileStreamResult DownloadFileStream(string fileName) { var filePath = Path.Combine(_environment.WebRootPath, "upload", fileName); var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); return new FileStreamResult(fileStream,"application/pdf") { FileDownloadName = fileName }; }
2. How the client uploads the file?
UploadFileResult.cs
public class UploadFileResult
{
public string Status { get; set; }
public string FileName { get; set; }
public long FileSize { get; set; }
}
public class UploadFileResult
{
public string Status { get; set; }
public string FileName { get; set; }
public long FileSize { get; set; }
}
Console application method
static void DemoUpload()
{
try
{
var fileInfo = new FileInfo(@"C:\Users\Demo\Downloads\yourfile.pdf");
var payloadData = new
{
ApiKey = "ABC-2id-34lkwk-dkad",
AttachmentType = "UHVE",
Sano = "uweor23"
};
var form = new MultipartFormDataContent();
//Add data model to multiForm Content
content.Add(new StringContent(payloadData.ApiKey), "apiKey");
content.Add(new StringContent(payloadData.AttachmentType), "attachmentType");
content.Add(new StringContent(payloadData.Sano), "Sano");
//Add file StreamContent to multiForm Content
var fileContent = new StreamContent(new FileStream(fileInfo.FullName, FileMode.Open));
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "File",
FileName = fileInfo.Name,
FileNameStar = fileInfo.Name
};
form.Add(fileContent);
var client = new HttpClient();
client.BaseAddress = new Uri("https://localhost:17104");
var result = client.PostAsync("/TestARAttachment/DemoFormDataUpload", form).Result;
var fileResult = result.Content.ReadAsAsync<UploadFileResult>().Result;
Console.WriteLine("***************");
Console.WriteLine("Status: " + result.StatusCode);
Console.WriteLine("File name: " + fileResult.Name);
Console.WriteLine("File size: " + fileResult.Length);
Console.WriteLine("***************");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
static void DemoUpload()
{
try
{
var fileInfo = new FileInfo(@"C:\Users\Demo\Downloads\yourfile.pdf");
var payloadData = new
{
ApiKey = "ABC-2id-34lkwk-dkad",
AttachmentType = "UHVE",
Sano = "uweor23"
};
var form = new MultipartFormDataContent();
//Add data model to multiForm Content
content.Add(new StringContent(payloadData.ApiKey), "apiKey");
content.Add(new StringContent(payloadData.AttachmentType), "attachmentType");
content.Add(new StringContent(payloadData.Sano), "Sano");
//Add file StreamContent to multiForm Content
var fileContent = new StreamContent(new FileStream(fileInfo.FullName, FileMode.Open));
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "File",
FileName = fileInfo.Name,
FileNameStar = fileInfo.Name
};
form.Add(fileContent);
var client = new HttpClient();
client.BaseAddress = new Uri("https://localhost:17104");
var result = client.PostAsync("/TestARAttachment/DemoFormDataUpload", form).Result;
var fileResult = result.Content.ReadAsAsync<UploadFileResult>().Result;
Console.WriteLine("***************");
Console.WriteLine("Status: " + result.StatusCode);
Console.WriteLine("File name: " + fileResult.Name);
Console.WriteLine("File size: " + fileResult.Length);
Console.WriteLine("***************");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
Main Method call
static void Main(string[] args)
{
DemoUpload();
}
static void Main(string[] args)
{
DemoUpload();
}
This article covered a step-by-step code example of HttpPost httpclient multipart/form-data to a server.
How to send or upload multipart/form-data to ASP.NET Core Web API, and how to download uploaded file is easy to do.
We created ASP.NET Core Web ApI 2 as a server side endpoint code and C# Console application to consume web API endpoint using HttpClient request.
1 Comments
Please share link on Github if it possible because this article is very useful? but some code left somewore else such as custom attributes
ReplyDelete