我的用户拥有需要由经过身份验证的用户下载的私人文件。我的服务器首先使用它自己的S3 app_id / secret_token凭据从S3下载文件。然后构建下载的文件并使用Rails' send_data方法。
Ruby(在Rails上):
# documents_controller.rb
def download
some_file = SomeFile.find(params[:id])
# download file from AWS S3 to server
data = open(some_file.document.url)
# construct and send downloaded file to client
send_data data.read, filename: some_file.document_identifier, disposition: 'inline', stream: 'true'
end
最初,我想直接从HTML模板触发下载。
HTML:
<!-- download-template.html -->
<a target="_self" ng-href="{{ document.download_url }}" download="{{document.file_name}}">Download</a>
看起来很简单,但问题是Angular的$ http拦截器没有捕获这种类型的外部链接点击,因此没有为服务器端身份验证附加相应的头文件。结果是401 Unauthorized Error。
相反,我需要使用ng-click触发下载,然后从角度控制器执行$ http.get()请求。
HTML:
<!-- download-template.html -->
<div ng-controller="DocumentCtrl">
<a ng-click="download(document)">Download</a>
</div>
使用Javascript:
// DocumentCtrl.js
module.controller( "DocumentCtrl",
[ "$http", "$scope", "FileSaver", "Blob",
function( $http, $scope, FileSaver, Blob ) {
$scope.download = function( document ) {
$http.get(document.download_url, {}, { responseType: "arraybuffer" } )
.success( function( data ) {
var blob = new Blob([data], { type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" });
FileSaver.saveAs(blob, document.file_name);
});
};
}]);
FileSaver是一个使用Blob保存文件的简单库(显然在客户端上)。
这让我通过了我的身份验证问题,但导致文件以不可读/不可用的格式保存/下载到客户端。
为什么文件以不可用的格式下载?
提前致谢。
答案 0 :(得分:1)
Angular的$ http方法需要配置为接受二进制数据响应。
Rails'send_data文档:
将给定的二进制数据发送到浏览器。这种方法类似于 render plain:data,还允许你指定是否浏览器 应将响应显示为文件附件(即在下载中) 对话框)或内联数据。您也可以设置内容类型 表观文件名和其他东西。
Angular的$http文档在$ http的 responseType 配置方面非常差。从本质上讲,需要通过将responseType设置为“arraybuffer”(见下文)来告诉$ http预期二进制数据响应。
$scope.download = function( document ) {
console.log("download: ", document);
$http({
url: document.download_url,
method: "GET",
headers: {
"Content-type": "application/json"
},
responseType: "arraybuffer" // expect to handle binary data response
}).success( function( data, status, headers ) {
var type = headers('Content-Type');
var blob = new Blob([data], { type: type });
FileSaver.saveAs(blob, document.file_name);
});
};
Angular的$http documentation可能比以下更具描述性:
用法
$ HTTP(配置);
参数
配置
responseType - {string} - 请参阅XMLHttpRequest.responseType。
答案 1 :(得分:0)
您好我有一个示例,说明如何从我的服务器下载angular:
我用GET请求调用该文件:
文件下载html(客户端):
<a ng-href="/api/downloadFile/{{download.id}}" type="submit" class="btn btn-primary col-lg-12 btn-modal-costume" >download</a>
文件下载java(服务器端):
public static Result download(String id) {
String content = null;
for (controllers.file file : files) {
if (file.getId().equals(id)){
content = file.getContent();
}
}
return ok(new java.io.File("/temp/" + id+ "file" + content)).as("application/force-download");
}
如果您愿意,可以在github project
中查看所有代码答案 2 :(得分:0)
我认为你使用javascript解决方案走在正确的轨道上,但只是有一个错字。在$http.get
调用中,您传递一个空对象作为第二个参数。这是{responseType: arraybuffer}
的options参数应该已经消失的地方。请在此处查看$http.get
的文档:
https://docs.angularjs.org/api/ng/service/ $ HTTP GET#