'Download file from API using javascript

I need to force download of file using JavaScript. I am using Angular and restangular to communicate with API. I am now working on file download action from API... API returns me raw bytes of that file and these headers:

Content-Disposition:attachment; filename="thefile"
Content-Length:2753

So I have raw bytes, but I do not know how to handle it to download this file to client...Can you provide me some solution of this issue? How can I handle returns response from server to open in client browser Save As dialog?

EDITED: Server does not send me content-type of the file...Also in call's headers need to be auth token so I cannot use direct open window with url.. Code is:

vm.downloadFile = function(fileId){
 var action = baseHelpers.one('files/' + fileId + '/content').get();
 action.then(function(result){});
}


Solution 1:[1]

My first guess would be: Just request that API URL directly and not with an asynchronous request. You should be able to do something like this in your code

$window.location = "http://example.org/api/download"

For a solution using RESTangular I found this snipped, maybe you can try it:

Restangular.one('attachments', idAtt).withHttpConfig({responseType: 'blob'}}.get({}, {"X-Auth-Token": 'token'}).then(function(response) {
    var url = (window.URL || window.webkitURL).createObjectURL(response);
    window.open(url);
});

Solution 2:[2]

It's difficult to answer without seeing your code calling the API, but in general the way you do this is to send a form rather than using ajax. Typically you'd have a hidden iframe with a name="downloadframe" or similar, and then use a form like this:

<form id="downloadform" target="downloadframe" method="POST" action="/the/api/endpoint">
<input type="hidden" name="apiParameter" value="parameter-value">
</form>

Then you'd fill in the fields of the form and submit it programmatically. Here's an example not using Angular, but adapting it would be simple (though not necessary):

var form = document.getElementById("downloadform");
form.apiParameter.value = "appropriate value";
form.submit();

When the browser gets the response, it sees the Content-Disposition header and asks the user where to save the file.

You can even build the form dynamically rather than using markup if you prefer.

Solution 3:[3]

I had an endpoint on .Net server

[HttpPost]
[Route("api/tagExportSelectedToExcel")]

and a React frontend with axios. The task was to add a button which downloads a file from this API. I spent several hours before found this solution. I hope it will be helpful for someone else.

This is what I did:

axios('/api/tagExportSelectedToExcel', {
    data: exportFilter,
    method: 'POST',
    responseType: 'blob'
}).then(res => resolveAndDownloadBlob(res));

Where resolveAndDownloadBlob:

/**
 * Resolved and downloads blob response as a file.
 * FOR BROWSERS ONLY
 * @param response
 */
function resolveAndDownloadBlob(response: any) {
    let filename = 'tags.xlsx';
    filename = decodeURI(filename);
    const url = window.URL.createObjectURL(new Blob([response.data]));
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute('download', filename);
    document.body.appendChild(link);
    link.click();
    window.URL.revokeObjectURL(url);
    link.remove();
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 T.J. Crowder
Solution 3 Michael Klishevich