2

I am reading a solution how to download a file from asp.net api here: https://stackoverflow.com/a/3605510/1881147

therefore I create an API handler as the following code:

public HttpResponseMessage Post([FromBody]dynamic result)
        {

            var localFilePath = graphDataService.SaveToExcel(graphVm, graphImgUrl);
            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
            response.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
            response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
            response.Content.Headers.ContentDisposition.FileName = "testing.xlsx";
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("MS-Excel/xls");

            return response;
            //return graphDataService.SaveToExcel(graphVm, graphImgUrl);
        }

This is my client side:

     $http({
            url: '/msexcel',
            method: 'post',
            params: { param: JSON.stringify(param) }
        }).success(function (data, status, headers, config) {
            console.log(data); //HOW DO YOU HANDLE the response here so it downloads?
        }).error(function (data, status, headers, config) {
            console.log(status);
        });

How do you do you handle the success so it downloads the file as an .xls file? thx

1

1 Answer 1

5

Instead of setting the response content type to MS-Excel/xls use the application/octet-stream.

public HttpResponseMessage GetFile()
{
    var localFilePath = graphDataService.SaveToExcel(graphVm, graphImgUrl);
    HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
    response.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
    response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
    response.Content.Headers.ContentDisposition.FileName = "testing.xlsx";
    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
    response.Content.Headers.Add("x-filename", "testing.xlsx"); //We will use this below
    return response;
}

The tricky part is then how to force the download from the response in the success callback. One solution is to make a blob from the response data and download that blob again. In IE we can then just save that blob but for most browsers we will need to fool the browser

$http({
    method: 'GET',
    url: Url,
    responseType: 'arraybuffer',
    headers: {
        'Authorization': Token,
        'Access-Control-Allow-Origin': '*',
    }
}).success(function (data, status, headers) {
    headers = headers();

    var filename = headers['x-filename'];
    var contentType = headers['content-type'];

    try {
        var blob = new Blob([data], { type: contentType });

        //Check if user is using IE
        var ua = window.navigator.userAgent;
        var msie = ua.indexOf("MSIE ");

        if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./))
        {
            window.navigator.msSaveBlob(blob, filename);
        }
        else  // If another browser, return 0
        {
            //Create a url to the blob
            var url = window.URL.createObjectURL(blob);
            var linkElement = document.createElement('a');
            linkElement.setAttribute('href', url);
            linkElement.setAttribute("download", filename);

            //Force a download
            var clickEvent = new MouseEvent("click", {
                "view": window,
                "bubbles": true,
                "cancelable": false
            });
            linkElement.dispatchEvent(clickEvent);
        }

    } catch (ex) {
        console.log(ex);
    }
}).error(function (message) {
    console.log(message);
});

NOTE: *The download attribute on the a-tag is only supported in HTML5. *I made this work by returning ByteArrayContent but the StreamContent should also work as it also returns binary data.

The solution is based on this great article but I included support for IE in this solution

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.