Downloading a File Using Web Api with Jquery or Knockout

This short walk-through is intended for those who work with WebApi and want to perform file download using Knockout or JQuery.

While working on a project that uses Knockout.js for front end scripting and Asp.Net Web API as back-end service layer, we had to implement file downloading functionality using Ajax.

Lets Code

[HttpGet] //Returns FileStream if file exists 
public HttpResponseMessage DownloadDocument(string fileUrl)
{
    try
    {
        Stream stream = FileHelper.GetFilesStream(fileUrl);
        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK)
        result.Content = new StreamContent(stream);
        result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
        result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        result.Content.Headers.ContentDisposition.FileName = "fileNameOfYourChoice";
        return result;
    }
    catch (NotFoundException exception)
    {
        Request.CreateErrorResponse(HttpStatusCode.NotFound, "File Not Found");
    }
    catch (Exception exception)
    {
        Request.CreateErrorResponse(HttpStatusCode.InternalServerError, exception.Message);
    }
}

This method in Api returns a FileStream, sets ContentDisposition and ContentType to tell browser the type of content is a file and browser popups save file dialog. GetFileStream method is defined in a Helper class that just converts a file into filestream

public class FileHelper
{
    public static Stream GetFilesStream(string fileUrl)
    {
        if (File.Exists(fileUrl))
        {
            return new FileStream(fileUrl, FileMode.Open);
        }

        throw new NotFoundException("File not found");
    }
}

Knockout Devs

Knockout developers have to create a view and a viewModel. The viewModel will expose a caller for API while the view will simply have an anchor tag which will have its click event bound to viewModel’s funtion.

ViewModel will have the following caller function

this.downloadDocument = function(attachment) {
      var resourceUri = '/api/Documents/DownloadDocument?fileUrl = ' + attachment.fileUrl;
      window.href.location = resourceUri;
    };

While the view’s anchor tag will look like

<a href = "" data-bind= "click: $parent.downloadDocument" > Download </a>

JQuery Devs

Jquery developers can define an anchor tag <a> in Html, build href  and set to the tage using Jquery.
<a href="'/api/Documents/DownloadDocuments? fileUrl = location\\my_file.asm" />
With the hope it helps 🙂 Cheers..

Leave a Reply