使用angular下载zip文件

时间:2014-03-14 17:22:27

标签: javascript angularjs content-type

我试图通过angular.js实现文件下载 该文件来自服务器的二进制格式,内容类型为application/octet-stream

下载是使用$resource的GET。查看传递给回调的参数(下面称为content),它是一个包含字节数组的对象,还包含$resource的属性列表。

尝试了多种方式来提供文件,但没有成功。

首先是:

...
var a = document.createElement('a');
a.href = "data:attachment/zip," + content;
a.download = zipName;
a.click();

在这种情况下,zip文件的内容为[object Object]

我尝试从对象中提取数组并将所有内容连接到字符串变量中。在这种情况下,zip文件大于正常大小。我必须在调用isArray: true的服务中设置$resource,否则无法从响应对象中提取字节内容。

我是这样做的:

var str = '';
for (var i = 0; i < content.length; i++) {
   str += content[i][0];
}

...
var a = document.createElement('a');
a.href = "data:attachment/zip," + str;
a.download = zipName;
a.click();

值得一提的是,在encodeURI上调用str会大幅增加下载的zip的大小,但存档仍然无效。

我还尝试从Blob创建str并将内容类型设置为application/octet-stream,但没有任何运气。

var blob = new Blob([str], {'type':"application/octet-stream"});
a.href = window.URL.createObjectURL(blob);
...

不知道我在这里丢失了什么,但在模拟点击下载之前,它看起来很难获得字节数组内容的正确格式并设置正确的href

非常感谢帮助。

由于

3 个答案:

答案 0 :(得分:1)

我刚找到你的帖子,并根据你的名单修正了答案。

  • 首先,您必须确保您的angular $ http请求包含,如下面的获取示例(include responseType: 'arraybuffer'

    $http.get('/downloadZip', {
                params: {
                    file: encodeURIComponent(filepath)
                },
                responseType: 'arraybuffer'
    //your code
    
  • 在您的成功或承诺处理程序中,您应该将window.URL.createObjectURL(blob)更改为URL.createObjectURL(blob)。实现类似于以下内容:

    var a = document.createElement('a');
    var blob = new Blob([data], {'type':"application/octet-stream"});
    a.href = URL.createObjectURL(blob);
    a.download = "filename.zip";
    a.click();
    

通过这些,您将创建一个新的锚元素并模拟打开它。正确修改了Blob,因为请求已被正确修改。

答案 1 :(得分:1)

不需要Angular。

var zip_file_path = "" //put inside "" your server path with file.zip
var zip_file_name = "" //put inside "" file name or something
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
a.href = zip_file_path;
a.download = zip_file_name;
a.click();
document.body.removeChild(a);

答案 2 :(得分:0)

如果有人仍在使用AngularJS(例如我)并且想要这样做,我接受了David的回答,并使其与angular $ resource一起使用,而不是直接使用较低级别的$ http。如果您使用$ resource,这应该对您有帮助:

    var myReportingResource = $resource(baseURL + '/mypath/:command', {},{
        getExportZip: {
            method: 'GET',
            params: {
                command: 'exportzip'
            },
            responseType: 'arraybuffer',
            // don't try to convert the zip to JSON
            // instead take the data that comes back and put it in an object under a content key
            transformResponse: function(data){
                return {content: data};
            }
        }
    });

    // call the resource like this
    myReportingResource.getExportZip(yourParams).$promise.then(function(zipData){
            // create a anchor element, stick the zip data in it, and click it to download
            var anchor = angular.element('<a/>');
            anchor.attr({
                href: URL.createObjectURL(new Blob([zipData.content], {'type':'application/octet-stream'})),
                download: 'myfilename.zip'
            })[0].click();

        });

您需要transformResponse位,因为否则AngularJS会将您的响应转换为JSON,这对于二进制数据是错误的。这就是为什么以后使用zipData.content将数据传递到Blob的原因。您可以摆脱content部分,这里有简单的错误处理代码。

自2019年5月起,此功能可在Chrome和Safari中使用。未在其他任何地方进行测试。