Skip to content

Instantly share code, notes, and snippets.

@jagmeet-chaudhary
Last active June 28, 2022 08:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jagmeet-chaudhary/e5ab82221400b12f23b4e138a7568348 to your computer and use it in GitHub Desktop.
Save jagmeet-chaudhary/e5ab82221400b12f23b4e138a7568348 to your computer and use it in GitHub Desktop.
Sample code showing various ways to upload files using asp.net web api. Includes server side code of API controller and console application acting as client for calling these API.
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net.Http;
using System.Text;
namespace FileUploadClient
{
class Program
{
const string uploadFilePath = @"E:\Uploads\Sendfiles\FlightPlan.pdf";
const string apiBaseAddress = "https://localhost:44390";
const string fileContentType = "application/pdf";
static void Main(string[] args)
{
Stopwatch watch = new Stopwatch();
watch.Start();
PostMultipartFormData();
Console.WriteLine($"Multipart formdata upload : {watch.Elapsed.TotalSeconds}");
watch.Restart();
PostMultipartRelated();
Console.WriteLine($"Multipart Related upload : {watch.Elapsed.TotalSeconds}");
watch.Restart();
PostJson();
Console.WriteLine($"Json upload : {watch.Elapsed.TotalSeconds}");
watch.Restart();
PostSimple();
Console.WriteLine($"Simple upload : {watch.Elapsed.TotalSeconds}");
Console.ReadLine();
}
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}");
}
static void PostMultipartRelated()
{
using var client = new HttpClient();
using var content = new MultipartContent("Related", "boundary-1");
// First part : Metadata
var customerInformation = new { CustomerId = "123123", CustomerName = "ABC Ltd." };
content.Add(new StringContent(JsonConvert.SerializeObject(customerInformation),Encoding.UTF8,"application/json"));
// Second part : File
var fileContent = new StreamContent(new FileStream(uploadFilePath, FileMode.Open));
fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(fileContentType);
content.Add(fileContent);
var requestUri = "/api/Upload/MultipartRelatedUpload";
client.BaseAddress = new Uri(apiBaseAddress);
var result = client.PostAsync(requestUri, content).Result;
Console.WriteLine($"Response : {result.StatusCode}");
}
static void PostSimple()
{
using var client = new HttpClient();
using var content = new ByteArrayContent(File.ReadAllBytes(uploadFilePath));
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(fileContentType);
var requestUri = "/api/Upload/SimpleUpload";
client.BaseAddress = new Uri(apiBaseAddress);
var result = client.PostAsync(requestUri, content).Result;
Console.WriteLine($"Response : {result.StatusCode}");
}
static void PostJson()
{
using var client = new HttpClient();
var fileContent = File.ReadAllBytes(uploadFilePath);
var jsonContent = new { CustomerId = "123123", CustomerName = "ABC Ltd.", ContentType = fileContentType, FileContent = Convert.ToBase64String(fileContent) };
var requestUri = "/api/Upload/JsonUpload";
client.BaseAddress = new Uri(apiBaseAddress);
var result = client.PostAsync(requestUri,new StringContent(JsonConvert.SerializeObject(jsonContent),Encoding.UTF8,"application/json")).Result;
Console.WriteLine($"Response : {result.StatusCode}");
}
}
}
using System;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.IO;
using Microsoft.Net.Http.Headers;
using ContentDispositionHeaderValue = Microsoft.Net.Http.Headers.ContentDispositionHeaderValue;
using MediaTypeHeaderValue = Microsoft.Net.Http.Headers.MediaTypeHeaderValue;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using MimeTypes;
namespace FileUpload.Controllers
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
var formValueProviderFactory = context.ValueProviderFactories
.OfType<FormValueProviderFactory>()
.FirstOrDefault();
if (formValueProviderFactory != null)
{
context.ValueProviderFactories.Remove(formValueProviderFactory);
}
var jqueryFormValueProviderFactory = context.ValueProviderFactories
.OfType<JQueryFormValueProviderFactory>()
.FirstOrDefault();
if (jqueryFormValueProviderFactory != null)
{
context.ValueProviderFactories.Remove(jqueryFormValueProviderFactory);
}
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
}
public class FileFormData
{
public string CustomerId { get; set; }
public string CustomerName { get; set; }
public IFormFile File { get; set; }
}
public class FileJsonData
{
public string CustomerId { get; set; }
public string CustomerName { get; set; }
public string ContentType { get; set; }
public string FileContent { get; set; }
}
[Route("api/[controller]")]
[ApiController]
public class UploadController : ControllerBase
{
const string fileUploadPath = "E:\\Uploads\\";
readonly Func<string, string, string, string,string> GetFilePath = (uploadType, customerId, fileExtenstion,folderPath) => Path.Combine(folderPath,$"{uploadType}_{customerId}_{Guid.NewGuid()}_{fileExtenstion}");
[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).Wait();
return Ok();
}
[HttpPost]
[Route("SimpleUpload")]
public IActionResult SimpleUpload()
{
var fileExtension = MimeTypeMap.GetExtension(Request.ContentType);
using var stream = System.IO.File.Create(GetFilePath("SimpleUpload", "None", fileExtension, fileUploadPath));
Request.BodyReader.AsStream().CopyToAsync(stream).Wait();
return Ok();
}
[HttpPost]
[Route("JsonUpload")]
public IActionResult JsonUpload([FromBody]FileJsonData jsonData)
{
// Check if the request contains multipart/form-data.
Byte[] bytes = Convert.FromBase64String(jsonData.FileContent);
var fileExtension = MimeTypeMap.GetExtension(jsonData.ContentType);
System.IO.File.WriteAllBytes(GetFilePath("SimpleUpload", "None", fileExtension, fileUploadPath), bytes);
return Ok();
}
[HttpPost]
[Route("MultipartRelatedUpload")]
[DisableFormValueModelBinding]
public IActionResult MultipartRelatedUpload()
{
var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), 73);
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
//Read metadata from first section
var section = reader.ReadNextSectionAsync().Result;
using var firstSectionReader = new StreamReader(section.Body);
var firstSectionContent = firstSectionReader.ReadToEndAsync().Result;
//Read file from second section
section = reader.ReadNextSectionAsync().Result;
var fileExtension = MimeTypeMap.GetExtension(section.ContentType);
using (var fileStream = System.IO.File.Create(GetFilePath("MultipartRelatedUpload", "None", fileExtension, fileUploadPath)))
{
section.Body.CopyToAsync(fileStream).Wait();
}
return Ok();
}
public static class MultipartRequestHelper
{
// Content-Type: multipart/form-data; boundary="----WebKitFormBoundarymx2fSWqWSd0OxQqq"
// The spec at https://tools.ietf.org/html/rfc2046#section-5.1 states that 70 characters is a reasonable limit.
public static string GetBoundary(MediaTypeHeaderValue contentType, int lengthLimit)
{
var boundary = HeaderUtilities.RemoveQuotes(contentType.Boundary).Value;
if (string.IsNullOrWhiteSpace(boundary))
{
throw new InvalidDataException("Missing content-type boundary.");
}
if (boundary.Length > lengthLimit)
{
throw new InvalidDataException(
$"Multipart boundary length limit {lengthLimit} exceeded.");
}
return boundary;
}
public static bool IsMultipartContentType(string contentType)
{
return !string.IsNullOrEmpty(contentType)
&& contentType.IndexOf("multipart/", StringComparison.OrdinalIgnoreCase) >= 0;
}
public static bool HasFormDataContentDisposition(ContentDispositionHeaderValue contentDisposition)
{
// Content-Disposition: form-data; name="key";
return contentDisposition != null
&& contentDisposition.DispositionType.Equals("form-data")
&& string.IsNullOrEmpty(contentDisposition.FileName.Value)
&& string.IsNullOrEmpty(contentDisposition.FileNameStar.Value);
}
public static bool HasFileContentDisposition(ContentDispositionHeaderValue contentDisposition)
{
// Content-Disposition: form-data; name="myfile1"; filename="Misc 002.jpg"
return contentDisposition != null
&& contentDisposition.DispositionType.Equals("form-data")
&& (!string.IsNullOrEmpty(contentDisposition.FileName.Value)
|| !string.IsNullOrEmpty(contentDisposition.FileNameStar.Value));
}
}
}
}
@prasanna32
Copy link

Hello Jagmeet,

Can I post stream data as below as a parameter? If yes, how will you pass stream using HttpClient.PostAsync ?

[HttpPost]
public async Task PostStream(System.IO.Stream stream)

Copy link

ghost commented Sep 30, 2021

Hi Jagmeet,

I see you have a using MimeTypes statement in UploadController.cs. What package is this from?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment