Как загрузить zip-файл в AngularJS/FilesaverJS

у меня есть сервисная функция, которая возвращает мне 3 файла результатов (2 текстовых файла, 1 zip-файл).

я хочу проверить заголовок ответа, чтобы увидеть, является ли файл zip или текстом, чтобы установить правильную конфигурацию для загрузки файла.

мой контроллер разрешил обещание от моей службы. если я загружаю текстовый файл -> файл говорит [объект объект]..

я видел в своем браузере, что тело ответа относится к типу содержимого: текст/обычный

я немного запутался :/

контроллер:

$scope.getResult = function(rid) {
        console.log($scope.id);
        GetResultFile.getResult($scope.id, rid)
        .then(function (data, headers) {
            //console.log(headers(Content-type));
            console.log("Download erfolgreich");
            console.log(data.status);
            var file = new Blob([data], {type: 'text/plain;charset=utf-8'});
            FileSaver.saveAs(file, 'test.txt');

        }, function (data) {
            console.log("Download ERROR!");
            console.log(data.status);
        })
    };      

оказание услуг :

.factory('GetResultFile',
['$http', '$q',
function ($http, $q) {

    var service = {};
    service.getResult = function(id, rid) {

        var deferred = $q.defer();

        $http
        .get('http://localhost:9999/v1/jmeter/' + id + '/results/' + rid, {cache: false})
        .then(function(data, status, headers, config) {
            if(data.status == 200) {
                console.log(data.status);
                deferred.resolve(data);
            }
            else {
                deferred.reject(data);
            }
        });
        return deferred.promise;                
    }
    return service;

Посмотреть:

<span ng-show="dataTable">
    <table>
        <tr ng-repeat="r in results">
            <td><a href="" ng-click="getResult(r.id)" download>{{r.name}}</a></td>
        </tr>
    </table>
</span>

Обновлять:

это мой сервис, в котором я устанавливаю тип ответа на arraybuffer

.factory('GetZip',
['$http', '$q',
function ($http, $q) {

    var service = {};
    service.getZip = function(id, rId) {

        var deferred = $q.defer();

        $http
        .get('http://localhost:9999/v1/jmeter/' + id + '/results/' + rId, {cache: false, responseType: 'arraybuffer'})
        .then(function(response) {
            if(response.status == 200) {
                console.log(response.status);
                deferred.resolve(response);
            }
            else {
                deferred.reject(response);
            }
        });
        return deferred.promise;                
    }
    return service;

это мой вызов в контроллере:

$scope.getResult = function(rId, rName) {
        console.log($scope.id);
        console.log(rName);
        GetResultFile.getResult($scope.id, rId)
        .then(function(response) {
            var data = "";
            var headerType = "";
            data = response.data;
            headerType = response.headers('content-type');
            console.log(response.headers('content-type'));
            console.log("Download erfolgreich");
            console.log(response);
            // zip data need to be handle with a binary stream
            if(headerType == 'application/zip;charset=UTF-8') {
                GetZip.getZip($scope.id, rId)
                .then(function(response) {
                    var file = new Blob([response.data], {type: "application/octet-stream"});
                    FileSaver.saveAs(file, rName);
                    console.log("zipper");
                }, function(response) {
                    console.log("Download ERROR");
                    console.log(response.status);
                })
            } else {
                var file = new Blob([data], {type: headerType});
                FileSaver.saveAs(file, rName);
                console.log("else");
            }
        }, function(response) {
            console.log("Download ERROR!");
            console.log(response.status);
        })
    };              

}])

но если я загружаю zip-файл, он все еще поврежден и ошибка при извлечении zip -.-


person Kai    schedule 09.01.2017    source источник
comment
Так в чем проблема на данный момент? В заголовке упоминаются zip-файлы, но вы спрашиваете о текстовых файлах в вопросе. Не могли бы вы подробнее рассказать о ..the file says [object object]?   -  person Ankh    schedule 09.01.2017
comment
упс, извините, текстовые файлы и zip-файл, я отредактирую   -  person Kai    schedule 09.01.2017


Ответы (2)


Для этого у вас должно быть 2 отдельных службы отдыха на бэкэнде, поэтому вместо одновременного обслуживания всех файлов и хранения их в браузере вы должны получить список доступных файлов из одной конечной точки отдыха, а затем по щелчку пользователя получить определенный файл из другой конечной точки отдыха. . Ваш сервис для файла может выглядеть примерно так:

function downloadFile(src) {
  let header, startIndex, filename;
  $http({
    method: 'GET',
    url: src,
    headers: {
      'Accept': 'text/html,application/xhtml+xml,application/xml,application/pdf;q=0.9,image/webp,*/*;q=0.8',
      'Upgrade-Insecure-Requests': 1
    },
    responseType: 'blob'
  }).then(function (successResponse) {
    header = unescape(successResponse.headers()['content-disposition']);
    startIndex = header.indexOf('filename=');
    filename = header.slice(startIndex + 10,-1);
    try{
      saveAs(successResponse.data, filename);
    }
    catch(error){
      // FileSaver error
    }
  }, function (errorResponse) {
    // Server error has occurred during file downloading.
}

Где вам нужно указать тип ответа, чтобы быть blob. Переменная src в этом примере будет конкретной конечной точкой, обслуживающей нужный файл (здесь она обслуживается контроллером на основе данных, полученных из списка доступных файлов, но вы можете создать ее здесь, если хотите, на основе идентификатора файла или чего-то еще). В этом случае бэкэнд обслуживает полное имя файла в открытом заголовке, поэтому вы можете извлечь его и сохранить файл с его правильным именем и форматом. Извлечение в этом примере было предназначено для определенного ответа на паузу, но вы должны иметь возможность изменить его в соответствии со своими потребностями.

Пример: заголовок размещения содержимого будет строкой, например:

Content-Disposition: attachment; filename="picture.png"

В этом случае сервис извлечет это имя, а Filesaver сохранит файл "picture.png".

person Ivan Sabol    schedule 10.01.2017
comment
Вы можете проверить мое обновление вопроса? до сих пор не работает .. - person Kai; 11.01.2017
comment
@Kai в вашем контроллере, var file=.... что такое данные? вы ничего не делаете с ответом, это должно быть что-то вроде response.data, также убедитесь, что rName является правильным именем файла, в настоящее время я не уверен, откуда вы его получаете. - person Ivan Sabol; 11.01.2017
comment
data = response.data и rName - это имя файла из представления, имя правильное, и данные выглядят хорошо, но если я разархивирую данные, возникает ошибка -.- - person Kai; 11.01.2017
comment
хорошо, я исправил это! спасибо за помощь - person Kai; 11.01.2017

Как скачать zip-файл в AngularJS

Чтобы загрузить двоичный тип файла, такой как zip-файл, важно установить responseType перед выполнением XHR.

var config = { responseType: "blob" };

var promise = $http.get(url, config);

promise
  .then(function onSuccess(response) {
    // Handle success
    var data = response.data;
    var status = response.status;
    var statusText = response.statusText;
    var headers = response.headers;
    var config = response.config;
    ...
  }).catch(function onError(response) {
    // Handle error
    var data = response.data;
    var status = response.status;
    var statusText = response.statusText;
    var headers = response.headers;
    var config = response.config;
    ...
  });

Для получения дополнительной информации см. Справочник по веб-API MDN — XHR responseType.

person georgeawg    schedule 09.01.2017
comment
можете ли вы проверить мое обновление вопроса, все еще ошибка - person Kai; 11.01.2017