Как загрузить байтовый массив в виде zip-файла в клиенте AngularJS? - PullRequest
0 голосов
/ 20 февраля 2019

Я уверен, что этот вопрос и подобные варианты задавались здесь много раз за эти годы.Я прошел почти все и до сих пор не могу выполнить это должным образом.

У меня есть конечная точка .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

К сожалениюэто приводит к повреждению файла архива, независимо от того, что я делаю с приведенным выше кодом.Утилита zip Window 10 жалуется, что архив не может быть открыт, даже если файл не пустой.Я пробовал следующее:

  • Установка responseType как blob в запросе $http.get() и прямая передача его в FileSaver.saveAs() метод
  • Передача application/zip идругие типы MIME для конструктора Blob
  • Передача { autoBOM: true } в метод FileSaver.saveAs()

Я подозреваю, что это проблема кодирования в качестве другого ASP.NET WebПриложение Forms может загрузить действительный zip-файл из той же конечной точки API.

Будем весьма благодарны за любые указатели.Заранее спасибо!

1 Ответ

0 голосов
/ 20 февраля 2019

Попробуйте это

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

Надеюсь, это поможет.

...