如何在 AngularJS 客户端中将字节数组下载为 zip 文件?
How to download a byte array as a zip file in an AngularJS client?
我敢肯定这个问题和类似的变体多年来已经在这里被问过很多次了。我已经经历了几乎所有的事情,但仍然无法正确执行。
我有一个 .NET Core API 端点,returns 一个表示 zip 文件的字节数组:
[HttpGet]
[Route("download/{fileId}/")]
public byte[] Download(long fileId)
{
...
}
我使用AngularJS的$http
服务,arraybuffer
作为responseType
发起请求:
// AngularJS service (fileApiService)
this.downloadFile = function (fileId) {
var url = apiUrl + 'download/' + fileId;
return $http.get(url, { responseType: 'arraybuffer' });
};
我得到了一个有效的回复,它的处理方式如下。我使用 FileSaver.js 访问 saveAs
方法和 Blob
构造函数:
// 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 () {
...
});
不幸的是,无论我对上述代码做了什么调整,这都会导致存档文件损坏。 Window 10 zip 实用程序抱怨即使文件不为空也无法打开存档。我尝试了以下方法:
- 在
$http.get()
请求中将 responseType
设置为 blob
并直接将其传递给 FileSaver.saveAs()
方法
- 将
application/zip
和其他 MIME 类型传递给 Blob
构造函数
- 将
{ autoBOM: true }
传递给 FileSaver.saveAs()
方法
我怀疑这是一个编码问题,因为另一个 ASP.NET Web 表单应用程序可以从同一个 API 端点下载有效的 zip 文件。
任何指点将不胜感激。提前致谢!
试试这个
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 () {
// ...
});
希望对您有所帮助。
我敢肯定这个问题和类似的变体多年来已经在这里被问过很多次了。我已经经历了几乎所有的事情,但仍然无法正确执行。
我有一个 .NET Core API 端点,returns 一个表示 zip 文件的字节数组:
[HttpGet]
[Route("download/{fileId}/")]
public byte[] Download(long fileId)
{
...
}
我使用AngularJS的$http
服务,arraybuffer
作为responseType
发起请求:
// AngularJS service (fileApiService)
this.downloadFile = function (fileId) {
var url = apiUrl + 'download/' + fileId;
return $http.get(url, { responseType: 'arraybuffer' });
};
我得到了一个有效的回复,它的处理方式如下。我使用 FileSaver.js 访问 saveAs
方法和 Blob
构造函数:
// 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 () {
...
});
不幸的是,无论我对上述代码做了什么调整,这都会导致存档文件损坏。 Window 10 zip 实用程序抱怨即使文件不为空也无法打开存档。我尝试了以下方法:
- 在
$http.get()
请求中将responseType
设置为blob
并直接将其传递给FileSaver.saveAs()
方法 - 将
application/zip
和其他 MIME 类型传递给Blob
构造函数 - 将
{ autoBOM: true }
传递给FileSaver.saveAs()
方法
我怀疑这是一个编码问题,因为另一个 ASP.NET Web 表单应用程序可以从同一个 API 端点下载有效的 zip 文件。
任何指点将不胜感激。提前致谢!
试试这个
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 () {
// ...
});
希望对您有所帮助。