Reputation: 1467
I'm sure this question and similar variants have been asked many times here over the years. I've gone through almost everything and am still unable to execute this properly.
I've a .NET Core API endpoint that returns a byte array that represents a zip file:
[HttpGet]
[Route("download/{fileId}/")]
public byte[] Download(long fileId)
{
...
}
I use AngularJS's $http
service with arraybuffer
as the responseType
to initiate a request:
// AngularJS service (fileApiService)
this.downloadFile = function (fileId) {
var url = apiUrl + 'download/' + fileId;
return $http.get(url, { responseType: 'arraybuffer' });
};
I get a valid response and it's handled like below. I use FileSaver.js to access the saveAs
method and the Blob
constructor:
// AngularJS controller
fileApiService.downloadFile(fileId)
.then(function (response) {
var data = response.data;
var blob = new Blob([data], { type: 'application/octet-stream' });
FileSaver.saveAs(blob, 'file.zip');
})
.catch(function () {
...
});
Unfortunately this results in a corrupted archive file regardless of whatever tweak I do to the above code. The Window 10 zip utility complains that the archive cannot be opened even if the file is not empty. I've tried the following:
responseType
as blob
in the $http.get()
request and directly passing that into FileSaver.saveAs()
methodapplication/zip
and other MIME types to the Blob
constructor{ autoBOM: true }
to the FileSaver.saveAs()
methodI'm suspecting that this is an encoding issue as another ASP.NET Web Forms application can download a valid zip file from the same API endpoint.
Any pointers would be greatly appreciated. Thanks in advance!
Upvotes: 0
Views: 5481
Reputation: 461
Try this
fileApiService.downloadFile(fileId)
.then(function (response) {
var data = response.data;
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512; // sliceSize represent the bytes to be process in each batch(loop), 512 bytes seems to be the ideal slice size for the performance wise
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, { type: contentType });
return blob;
}
var blob = b64toBlob(data, 'application/octet-stream');
FileSaver.saveAs(blob, 'file.zip');
})
.catch(function () {
// ...
});
Hope this helps.
Upvotes: 1