File upload is quite an important topic for Web API endpoints or for API-driven applications, and sure enough there are some nice changes to the MultiPartFormDataStreamProvider
Let’s have a look at how you could upload files to your ASP.NET Web API.
MultipartFormPost
This method has five parameters. You can increase/decrease the number of parameters according to your requirement. These five parameters are,
Let’s have a look at how you could upload files to your ASP.NET Web API.
MultipartFormPost
This method has five parameters. You can increase/decrease the number of parameters according to your requirement. These five parameters are,
- Posturl
This must be the url to which you want to post the form.
- userAgentThis is up to your requirement; if needed, then pass the value as required.
- postParametersThis is of type Dictionary. You can pass the parameter name and value as “key-value”
- headerkeyThis must be the name of the header that needs to be passed. In this example, I have used it as a string which can be used to pass a single header. If the header is not required, you can ignore this parameter.
- headervalueThis must be the value of the header to be passed.
Let’s modify our controller now
public class UploadingController : ApiController
{
public Task<IEnumerable<FileDesc>> Post()
{
var folderName = "uploads";
var PATH = HttpContext.Current.Server.MapPath("~/"+folderName);
var rootUrl = Request.RequestUri.AbsoluteUri.Replace(Request.RequestUri.AbsolutePath, String.Empty);
if (Request.Content.IsMimeMultipartContent())
{
var streamProvider = new CustomMultipartFormDataStreamProvider(PATH);
var task = Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith<IEnumerable<FileDesc>>(t =>
{
if (t.IsFaulted || t.IsCanceled)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
var fileInfo = streamProvider.FileData.Select(i => {
var info = new FileInfo(i.LocalFileName);
return new FileDesc(info.Name, rootUrl+"/"+folderName+"/"+info.Name, info.Length / 1024);
});
return fileInfo;
});
return task;
}
else
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
}
}
}
|
Returning some meaningful info
Finally, you may want to return some information about the uploaded files to the client. If that’s the case, one way to do it is to use a helper class (which was used already in the older post):
2
3
4
5
6
7
8
9
10
11
12
13
|
public class FileDesc
{
public string Name { get; set; }
public string Path { get; set; }
public long Size { get; set; }
public FileDesc(string n, string p, long s)
{
Name = n;
Path = p;
Size = s;
}
}
|
However, now, you can easily derive from the default MultiPartFormDataStreamProvider and provide your own naming mechanism.
Let’s have a look at such simple example:
public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
{
public CustomMultipartFormDataStreamProvider(string path) : base(path)
{}
public override string GetLocalFileName(System.Net.Http.Headers.HttpContentHeaders headers)
{
var name = !string.IsNullOrWhiteSpace(headers.ContentDisposition.FileName) ? headers.ContentDisposition.FileName : "NoName";
return name.Replace(""",string.Empty); //this is here because Chrome submits files in quotation marks which get treated as part of the filename and get escaped
}
}
So now, instead of void we return a List<FileDesc> which can provide the client information about each of the uploaded files: its name, path and size.