Download File from an ASP.NET Web API Method Using Angularjs

Trying to download file from server using angularJS and c# webapi

Added arraybuffer as a responsetype of the GET request, now the browser interprets the files correctly.

    /******** FILE DOWNLOAD  **********/
$scope.downloadFiles = function (file) {
$http({
method: 'GET',
cache: false,
url: host + 'api/Files/GetFile',
responseType:'arraybuffer',
headers: {
'Content-Type': 'application/json; charset=utf-8',
'fileID': file.id
}

Download file from an ASP.NET Web API method using AngularJS

Support for downloading binary files in using ajax is not great, it is very much still under development as working drafts.

Simple download method:

You can have the browser download the requested file simply by using the code below, and this is supported in all browsers, and will obviously trigger the WebApi request just the same.

$scope.downloadFile = function(downloadPath) { 
window.open(downloadPath, '_blank', '');
}
Ajax binary download method:

Using ajax to download the binary file can be done in some browsers and below is an implementation that will work in the latest flavours of Chrome, Internet Explorer, FireFox and Safari.

It uses an arraybuffer response type, which is then converted into a JavaScript blob, which is then either presented to save using the saveBlob method - though this is only currently present in Internet Explorer - or turned into a blob data URL which is opened by the browser, triggering the download dialog if the mime type is supported for viewing in the browser.

Internet Explorer 11 Support (Fixed)

Note: Internet Explorer 11 did not like using the msSaveBlob function if it had been aliased - perhaps a security feature, but more likely a flaw, So using var saveBlob = navigator.msSaveBlob || navigator.webkitSaveBlob ... etc. to determine the available saveBlob support caused an exception; hence why the code below now tests for navigator.msSaveBlob separately. Thanks? Microsoft

// Based on an implementation here: web.student.tuwien.ac.at/~e0427417/jsdownload.html
$scope.downloadFile = function(httpPath) {
// Use an arraybuffer
$http.get(httpPath, { responseType: 'arraybuffer' })
.success( function(data, status, headers) {

var octetStreamMime = 'application/octet-stream';
var success = false;

// Get the headers
headers = headers();

// Get the filename from the x-filename header or default to "download.bin"
var filename = headers['x-filename'] || 'download.bin';

// Determine the content type from the header or default to "application/octet-stream"
var contentType = headers['content-type'] || octetStreamMime;

try
{
// Try using msSaveBlob if supported
console.log("Trying saveBlob method ...");
var blob = new Blob([data], { type: contentType });
if(navigator.msSaveBlob)
navigator.msSaveBlob(blob, filename);
else {
// Try using other saveBlob implementations, if available
var saveBlob = navigator.webkitSaveBlob || navigator.mozSaveBlob || navigator.saveBlob;
if(saveBlob === undefined) throw "Not supported";
saveBlob(blob, filename);
}
console.log("saveBlob succeeded");
success = true;
} catch(ex)
{
console.log("saveBlob method failed with the following exception:");
console.log(ex);
}

if(!success)
{
// Get the blob url creator
var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;
if(urlCreator)
{
// Try to use a download link
var link = document.createElement('a');
if('download' in link)
{
// Try to simulate a click
try
{
// Prepare a blob URL
console.log("Trying download link method with simulated click ...");
var blob = new Blob([data], { type: contentType });
var url = urlCreator.createObjectURL(blob);
link.setAttribute('href', url);

// Set the download attribute (Supported in Chrome 14+ / Firefox 20+)
link.setAttribute("download", filename);

// Simulate clicking the download link
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
link.dispatchEvent(event);
console.log("Download link method with simulated click succeeded");
success = true;

} catch(ex) {
console.log("Download link method with simulated click failed with the following exception:");
console.log(ex);
}
}

if(!success)
{
// Fallback to window.location method
try
{
// Prepare a blob URL
// Use application/octet-stream when using window.location to force download
console.log("Trying download link method with window.location ...");
var blob = new Blob([data], { type: octetStreamMime });
var url = urlCreator.createObjectURL(blob);
window.location = url;
console.log("Download link method with window.location succeeded");
success = true;
} catch(ex) {
console.log("Download link method with window.location failed with the following exception:");
console.log(ex);
}
}

}
}

if(!success)
{
// Fallback to window.open method
console.log("No methods worked for saving the arraybuffer, using last resort window.open");
window.open(httpPath, '_blank', '');
}
})
.error(function(data, status) {
console.log("Request failed with status: " + status);

// Optionally write the error out to scope
$scope.errorDetails = "Request failed with status: " + status;
});
};
Usage:
var downloadPath = "/files/instructions.pdf";
$scope.downloadFile(downloadPath);

Notes:

You should modify your WebApi method to return the following headers:

  • I have used the x-filename header to send the filename. This is a custom header for convenience, you could however extract the filename from the content-disposition header using regular expressions.

  • You should set the content-type mime header for your response too, so the browser knows the data format.

I hope this helps.

Downloading PDF with AngularJS and WebAPI

that should do the trick,

  $http({
url: 'https://localhost/api/download-statement/1',
method: "POST",
responseType: 'arraybuffer'
}).success(function (data, status, headers, config) {
var blob = new Blob([data], {type: "application/pdf"});
var objectUrl = URL.createObjectURL(blob);
window.open(objectUrl);
}).error(function (data, status, headers, config) {
});

Download Excel from Asp.net Web API 2 using AngularJS

The code below did the magic if anyone else doing the same with Restangular, hope it helps!

(function () {
'use strict';
angular
.module('app.cobie.export')
.service('CobieExportDataService', ['Restangular', 'FileSaver', 'Blob',
function (Restangular, FileSaver, Blob) {

this.exportToCobie = function (projectId) {
toastr.info('Exporting COBie data', 'Info');
return Restangular.withConfig(function(RestangularConfigurer) {
RestangularConfigurer.setDefaultHttpFields({
cache : false ,
responseType: "arraybuffer",
});
}).one("export/" + projectId).get().then(function (res) {
var data = new Blob([res], { type: 'application/vnd.ms-excel' });
FileSaver.saveAs(data, 'export.xls');
})
}

}]);
})();

AngularJS save image file sent from Web API 2

The provided value 'arrayBuffer' is not a valid enum value of type XMLHttpRequestResponseType.

Use arraybuffer all lowercase:

    $http({
url: State.Endpoint + "/api/account/picture",
method: "GET",
//responseType: 'arrayBuffer'
//USE arraybuffer lowercase
responseType: 'arraybuffer'
//OR
//responseType: 'blob'
})

When the responseType is not valid, the XHR API defaults to decoding the response as UTF-8. This corrupts binary files such as JPEG images.

For more information, see MDN XHR Web API - responseType.


Creating a Download Button

Instead of creating a <a download></a> element with JavaScript DOM manipulation, consider using the AngularJS framework.

This is an example of a Download button that becomes active after the data is loaded from the server:

<a download="data_{{files[0].name}}" xd-href="data">
<button ng-disabled="!data">Download</button>
</a>

The xdHref Directive

app.module("myApp").directive("xdHref", function() {
return function linkFn (scope, elem, attrs) {
scope.$watch(attrs.xdHref, function(newVal) {
if (newVal) {
elem.attr("href", newVal);
}
});
};
});

The DEMO on PLNKR.



Related Topics



Leave a reply



Submit