Handling File Downloads in Web API using C# and JavaScript

Web API is a powerful tool for creating web-based applications that can be accessed by various clients such as web browsers, mobile devices, and desktop applications. One of the common use cases of Web API is to allow clients to download files from the server. In this article, we will discuss how to create a Web API action method that allows a user to download a sample file and a JavaScript function that makes an AJAX call to the Web API to initiate the download.

Let’s start by looking at the Web API action method. The following code snippet is an example of such a method:

[Route("api/AssuranceFileApi/DownloadSampleFile")]
[HttpGet]
public async Task<HttpResponseMessage> DownloadSampleFile()
{
    string path = HostingEnvironment.MapPath("~/Documents/AssuranceFiles/Assured Persons.xlsx");
    // Check if file exists
    if (!File.Exists(path))
    {
        return Request.CreateResponse(HttpStatusCode.NotFound);
    }

    // Read file into memory
    var memory = new MemoryStream();
    using (var stream = new FileStream(path, FileMode.Open))
    {
        await stream.CopyToAsync(memory);
    }

    memory.Position = 0;

    // Return file
    var response = new HttpResponseMessage(HttpStatusCode.OK);
    response.Content = new StreamContent(memory);
    response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(GetContentType(path));

    return response;
}

This code is an example of a Web API action method that allows the user to download a sample file. The method is decorated with the Route attribute, specifying that it can be accessed at the “api/AssuranceFileApi/DownloadSampleFile” URL. The method also has the HttpGet attribute, indicating that it can only be accessed using the GET HTTP verb.

The method starts by specifying the path of the file that is to be downloaded. In this case, the file is located in the “Documents/AssuranceFiles” folder and is named “Assured Persons.xlsx”. The method then uses the File.Exists method to check if the file exists. If it does not, the method returns a response with a status code of “NotFound”.

If the file does exist, the method creates a new MemoryStream object and uses a FileStream to read the contents of the file into memory. The MemoryStream’s position is then set to 0 to ensure that the file can be read from the beginning.

The method then creates a new HttpResponseMessage object with a status code of “OK” and sets its Content property to a new StreamContent object, which is initialized with the memory stream containing the file contents. The ContentType header is set using the GetContentType method, which returns the appropriate content type based on the file’s extension. Finally, the method returns the HttpResponseMessage object, which will send the file to the client.

private string GetContentType(string path)
        {
            var ext = Path.GetExtension(path).ToLowerInvariant();
            switch (ext)
            {
                case ".xlsx":
                    return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
                case ".xls":
                    return "application/vnd.ms-excel";
                default:
                    return "application/octet-stream";
            }
        }

The GetContentType method takes a single parameter, the path of the file, and uses the Path.GetExtension method to get the file’s extension. It then uses a switch statement to determine the appropriate content type based on the file’s extension. If the extension is “.xlsx”, the content type is set to "application/vnd.openxmlformats-officedocument.

The JavaScript function uses the jQuery $.ajax method to make the call to the Web API and handles the successful response by creating an anchor element, setting its properties and triggering a click event to initiate the download.

function DownloadSample() {
        $.ajax({
            type: 'GET',
            url: '/api/AssuranceFileApi/DownloadSampleFile',
            xhrFields: {
                responseType: 'blob'
            },
            success: function (data) {
                var a = document.createElement('a');
                var url = window.URL.createObjectURL(data);
                a.href = url;
                a.download = 'sample.xlsx';
                a.click();
                window.URL.revokeObjectURL(url);
            },
            error: function () { }
        });
    }

Conclustion:
We have discussed how to create a Web API action method that allows clients to download a sample file and a JavaScript function that makes an AJAX call to the Web API to initiate the download.
The Web API action method first checks if the file exists, if it does it reads the file into memory and creates an HttpResponseMessage object with the file as its content and appropriate content type.
This approach allows for a seamless download experience for the end-user and is a common pattern for handling file downloads in Web API based applications.