如何在AngularJS客户端中将字节数组下载为zip文件?

问题描述 投票:0回答:1

我相信多年来这里已经多次询问过这个问题和类似的变体。我已经完成了几乎所有事情,仍然无法正确执行此操作。

我有一个.NET Core API端点,它返回一个代表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 () {
            ...
        });

response

不幸的是,无论我对上述代码做了什么调整,都会导致存档文件损坏。 Window 10 zip实用程序抱怨即使文件不为空,也无法打开存档。我尝试过以下方法:

  • responseType请求中将blob设置为$http.get()并直接将其传递给FileSaver.saveAs()方法
  • application/zip和其他MIME类型传递给Blob构造函数
  • { autoBOM: true }传递给FileSaver.saveAs()方法

我怀疑这是一个编码问题,因为另一个ASP.NET Web窗体应用程序可以从同一API端点下载有效的zip文件。

任何指针都将非常感激。提前致谢!

angularjs blob angular-http arraybuffer filesaver.js
1个回答
1
投票

试试这个

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 () {
    // ...
});

希望这可以帮助。

© www.soinside.com 2019 - 2024. All rights reserved.