本文介绍了如何在AngularJS / FilesaverJS中下载zip文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个服务功能,它返回3个结果文件(2个文本文件,1个zip文件)。

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

我想查看响应的标题,看看如果文件是zip或文本来设置正确的配置以下载文件。

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.

我的控制器解决了我的服务承诺。如果我下载一个文本文件 - >文件说[object object] ..

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

我在浏览器中看到响应体来自content-type:text /普通

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

我有点困惑:/

控制器:

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

更新:

这是我的服务其中我将responsetype设置为arraybuffer

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

}])

但如果我下载zip文件,它仍然损坏并且在提取zip时出错--.-

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

推荐答案

你应该有2个单独的休息服务在后端为此而不是同时提供所有文件并将它们保存在浏览器中,您应该从一个休息端点检索可用文件列表,然后在用户单击从另一个休息端点检索特定文件。您的文件服务可能如下所示:

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

您需要将响应类型指定为blob。此示例中的变量src将是特定的endpoind提供所需的文件(这里它是基于数据检索从控制器提供的d从可用文件列表中,但如果你想根据文件的id或其他东西,你可以在这里建立它。在这种情况下,后端在公开的标题中提供完整的文件名,因此您可以提取它并使用正确的名称和格式保存文件。此示例中的提取是针对特定的休息响应,但您应该能够根据需要进行更改。

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"

在这种情况下,服务将提取该名称,而Filesaver将保存文件 picture.png。

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

这篇关于如何在AngularJS / FilesaverJS中下载zip文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-05 15:06