Multiple file upload with ASP.NET WebApi
Upload multiple files using WebApi REST service
Taking out business logic from the application allows different clients running on a different platform to use same logic. REST API is a great way to decuple business logic and make it available to different clients on a different platforms.
To upload files using WebApi we first need to define an action in a WebApi controller to handle files posted to the endpoint.
ASP.NET WebAPI Controller Action
First we define the relative path to a folder where we are going to store files uploaded to WebApi
<appSettings> <add key="fileUploadFolder" value="~/Uploaded"/> </appSettings>
To make ajax calls work make sure Cross Origin Resource Sharing (CORS) is enabled on WebApi side http://bit.ly/2CMISFy
Controller action name will handle all POST requests to UploadController.
using System.Configuration; using System.IO; using System.Net; using System.Net.Http; using System.Web; using System.Web.Hosting; using System.Web.Http; namespace FileUploader.Web.Api.Controllers { public class UploadController : ApiController { [HttpPost] public HttpResponseMessage Post() { var httpContext = HttpContext.Current; // Check for any uploaded file if (httpContext.Request.Files.Count > 0) { //Loop through uploaded files for (int i = 0; i < httpContext.Request.Files.Count; i++) { HttpPostedFile httpPostedFile = httpContext.Request.Files[i]; if (httpPostedFile != null) { // Construct file save path var fileSavePath = Path.Combine(HostingEnvironment.MapPath(ConfigurationManager.AppSettings["fileUploadFolder"]), httpPostedFile.FileName); // Save the uploaded file httpPostedFile.SaveAs(fileSavePath); } } } // Return status code return Request.CreateResponse(HttpStatusCode.Created); } } }
Post from HTML
Since WebApi relies on HTTP protocol, posting to WebApi does not require any code. In fact you can do it with a simple HTML.
<!DOCTYPE html> <html> <head> <title>File upload form</title> </head> <body> <form method="post" action="http://localhost:57584/Api/Upload"> <div> <label for="file1">File 1</label> <input type="file" id="file1" name="file1" /> </div> <div> <label for="file1">File 2</label> <input type="file" id="file2" name="file2" /> </div> <div> <label for="file1">File 3</label> <input type="file" id="file3" name="file3" /> </div> <button type="submit">Upload files</button> </form> </body> </html>
To make it even simpler, we can add multiple attribute to file input and we can use single HTML tag for picking multiple files for upload.
<!DOCTYPE html> <html> <head> <title>File upload form</title> </head> <body> <form method="post" action="http://localhost:57584/Api/Upload" enctype="multipart/form-data"> <div> <label for="files">Files</label> <input type="file" id="files" name="files" multiple="multiple" /> </div> <button type="submit">Upload files</button> </form> </body> </html>
Since WebApi is acting as a data provider, it does not give any meaningful response to HTML page that is doing the post, so real scenario of file posting file directly from HTML page is not that much real life scenario. The HTML above is more to demonstrate how WebApi can support even dummy client as a static HTML page.
Post from JavaScript (jQuery)
More realistic scenario for uploading files through WebApi is JavaScript client. Since WebApi responds with the status code, we can write the logic to show the proper information on the HTML page, plus JavaScript can provide asynchronous upload, meaning no need for a page refresh in order to upload file.
$(document).ready(function () { $('#buttonUpload').on('click', function () { var data = new FormData(); var files = $("#files").get(0).files; // Add the uploaded file to the form data collection if (files.length > 0) { for (f = 0; f < files.length; f++) { data.append("UploadedImage", files[f]); } } // Ajax upload $.ajax({ type: "POST", url: $("#formUpload").attr("action"), contentType: false, processData: false, data: data }); }); });
To make this jQuery script work we need to make sure DOM element ids match the ones referenced in jQuery
<form method="post" action="http://localhost:57584/Api/Upload" enctype="multipart/form-data" id="formUpload"> <div> <label for="files">Files</label> <input type="file" id="files" name="files" multiple="multiple" /> </div> <button type="button" id="buttonUpload">Upload files</button> </form>
Post from C# code
To upload data from C# code we can use System.Net.HttpClient class to simulate form submit via POST method
static bool Upload(String endpointUrl,IEnumerable<String> filePaths) { using (var client = new HttpClient()) using (var formData = new MultipartFormDataContent()) { foreach (String filePath in filePaths) { formData.Add(new ByteArrayContent(File.ReadAllBytes(filePath)), Path.GetFileNameWithoutExtension(filePath), Path.GetFileName(filePath)); } var response = client.PostAsync(endpointUrl, formData).Result; if (!response.IsSuccessStatusCode) { return false; } return true; } }
Now just to invoke it
var uploaded = Upload( "http://localhost:57584/Api/Upload", new DirectoryInfo(@"C:\Temp\TestFiles").GetFiles().Select(f => f.FullName));
References
Disclaimer
Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.
Comments for this article