如何在 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 实用程序抱怨即使文件不为空也无法打开存档。我尝试了以下方法:

我怀疑这是一个编码问题,因为另一个 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 () {
    // ...
});

希望对您有所帮助。