How to download a zip file in AngularJS / FilesaverJS [duplicate]

大兔子大兔子 提交于 2019-12-04 05:40:25

问题


i have a service function which return me 3 result files(2 text files, 1 zip file).

i want to check the header of the response to see if the file is a zip or a text to set the right configuration to download the file.

my controller resolved the promise from my service. if i download a text file -> the file says [object object] ..

i have seen in my browser that the response body is from content-type: text/plain

i am bit confused :/

controller :

$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);
        })
    };      

service :

.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;

view:

<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>

Update:

this is my service where i set the responsetype to 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;

this is my call in controller :

$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);
        })
    };              

}])

but if i download the zip file, its still corrupt and a error while extract the zip -.-


回答1:


You should have 2 separate rest services on backend for this so instead of serving all files at the same time and holding them in browser, you should retrieve list of available files from one rest endpoint and then on user's click retrieve specific file from another rest endpoint. Your service for file could look something like this:

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.
}

Where you need to specify response type to be blob. Variable src in this example would be specific endpoind serving desired file (here it's served from controller based on data retrieved from list of files available but you can build it here if you want based on file's id or something). In this case backend is serving full file name in exposed header so you can extract it and save file with it's proper name and format. Extraction in this example was for specific rest response but you should be able to change it to suite your needs.

Example: content disposition header would be string, something like:

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

In this case service would extract that name and Filesaver would save file "picture.png".




回答2:


How to download a zip file in AngularJS

To download a binary file type such as a zip file, it is important to set the responseType before doing the 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;
    ...
  });

For more information, see MDN Web API Reference - XHR responseType.



来源:https://stackoverflow.com/questions/41551553/how-to-download-a-zip-file-in-angularjs-filesaverjs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!