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>
    
Note

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.


About the author

DEJAN STOJANOVIC

Dejan is a passionate Software Architect/Developer. He is highly experienced in .NET programming platform including ASP.NET MVC and WebApi. He likes working on new technologies and exciting challenging projects

CONNECT WITH DEJAN  Loginlinkedin Logintwitter Logingoogleplus Logingoogleplus

JavaScript

read more

SQL/T-SQL

read more

Umbraco CMS

read more

PowerShell

read more

Comments for this article