如何在 AngularJS / FilesaverJS 中下载 zip 文件
How to download a zip file in AngularJS / FilesaverJS
我有一个服务功能,return 我有 3 个结果文件(2 个文本文件,1 个 zip 文件)。
我想检查响应的 header 以查看文件是 zip 还是文本,以设置正确的配置来下载文件。
我的控制者解决了我服务的承诺。如果我下载一个文本文件 -> 文件显示 [object object] ..
我在浏览器中看到响应 body 来自 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>
更新:
这是我的服务,我将响应类型设置为 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 时出错 -.-
如何在 AngularJS
中下载 zip 文件
要下载 zip 文件等二进制文件类型,在执行 XHR 之前设置 responseType
很重要。
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;
...
});
有关详细信息,请参阅 MDN Web API Reference - XHR responseType。
为此,您应该在后端有 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 将是为所需文件提供服务的特定端点(此处它是根据从可用文件列表中检索到的数据从控制器提供的,但如果您愿意,可以根据文件的 ID 或其他内容在此处构建它)。在这种情况下,后端在公开 header 中提供完整的文件名,因此您可以提取它并使用正确的名称和格式保存文件。此示例中的提取是针对特定的休息响应,但您应该能够更改它以满足您的需要。
示例:内容配置 header 将是字符串,类似于:
Content-Disposition: attachment; filename="picture.png"
在这种情况下,服务将提取该名称,而 Filesaver 将保存文件 "picture.png"。
我有一个服务功能,return 我有 3 个结果文件(2 个文本文件,1 个 zip 文件)。
我想检查响应的 header 以查看文件是 zip 还是文本,以设置正确的配置来下载文件。
我的控制者解决了我服务的承诺。如果我下载一个文本文件 -> 文件显示 [object object] ..
我在浏览器中看到响应 body 来自 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>
更新:
这是我的服务,我将响应类型设置为 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 时出错 -.-
如何在 AngularJS
中下载 zip 文件要下载 zip 文件等二进制文件类型,在执行 XHR 之前设置 responseType
很重要。
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;
...
});
有关详细信息,请参阅 MDN Web API Reference - XHR responseType。
为此,您应该在后端有 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 将是为所需文件提供服务的特定端点(此处它是根据从可用文件列表中检索到的数据从控制器提供的,但如果您愿意,可以根据文件的 ID 或其他内容在此处构建它)。在这种情况下,后端在公开 header 中提供完整的文件名,因此您可以提取它并使用正确的名称和格式保存文件。此示例中的提取是针对特定的休息响应,但您应该能够更改它以满足您的需要。
示例:内容配置 header 将是字符串,类似于:
Content-Disposition: attachment; filename="picture.png"
在这种情况下,服务将提取该名称,而 Filesaver 将保存文件 "picture.png"。