Javascript 使用$http.get()-OAuth身份验证下载带有Angular的远程文件
我的用户有需要由经过身份验证的用户下载的私人文件。我的服务器首先使用自己的S3应用程序id/secret令牌凭据从S3下载文件。然后使用Rails的方法构造下载的文件并发送给客户端 Ruby(在Rails上): 最初,我想直接从HTML模板进行触发下载 HTML: 是一个使用blob保存文件的简单库(显然是在客户机上) 这使我通过了身份验证问题,但导致文件以不可读/不可用的格式保存/下载到客户端 为什么下载的文件格式不可用?Javascript 使用$http.get()-OAuth身份验证下载带有Angular的远程文件,javascript,ruby-on-rails,angularjs,amazon-s3,oauth,Javascript,Ruby On Rails,Angularjs,Amazon S3,Oauth,我的用户有需要由经过身份验证的用户下载的私人文件。我的服务器首先使用自己的S3应用程序id/secret令牌凭据从S3下载文件。然后使用Rails的方法构造下载的文件并发送给客户端 Ruby(在Rails上): 最初,我想直接从HTML模板进行触发下载 HTML: 是一个使用blob保存文件的简单库(显然是在客户机上) 这使我通过了身份验证问题,但导致文件以不可读/不可用的格式保存/下载到客户端 为什么下载的文件格式不可用? 提前感谢。您好,我举了一个示例,说明如何使用angular从服务器下载
提前感谢。您好,我举了一个示例,说明如何使用angular从服务器下载文件: 我使用GET请求调用该文件: 文件下载html(客户端):
如果您愿意,您可以看到myAngular的$http方法中的所有代码都需要配置为接受二进制数据响应 Rails的文档: 将给定的二进制数据发送到浏览器。此方法类似于 呈现普通:数据,但也允许您指定浏览器 应将响应显示为文件附件(即在下载中 对话框)或作为内联数据。您还可以设置内容类型 明显的文件名等 Angular的文档对于$http的responseType的配置非常糟糕。本质上,$http需要通过将responseType设置为“arraybuffer”(见下文)来被告知需要一个二进制数据响应 Angular’s可能比以下内容更具描述性: 用法 $http(config) 论据 配置 responseType-{string}-请参阅
我认为您使用javascript解决方案的方向是正确的,但只是有一个输入错误。在
$http.get
调用中,传递一个空对象作为第二个参数。这就是带有{responseType:arraybuffer}
的options参数应该消失的地方。有关$http.get
的信息,请参见文档:
$http#get您必须使用文件保存器吗?您是否尝试过
window.navigator.msSaveOrOpenBlob
和window.open(objectUrl)
?我不需要使用FileSaver,但使用window.navigator.msSaveOrOpenBlob和window.open(objectUrl)都会导致相同的问题:无法读取文件格式。仍然是这样的情况,被包装/构造的文件被Blob再次包装/构造。嗨,Ariel,感谢您的响应,但仍然绕过Angular的$http拦截器,因此跳过了身份验证。在我的代码中,我使用了restAngular,但在文件下载的情况下,我不得不这样使用它,因为如果不是,它将返回文件作为后台请求,并且不会下载它。或者,您需要移动到新的url,仅用于GET请求和下载。
# 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
<!-- download-template.html -->
<a target="_self" ng-href="{{ document.download_url }}" download="{{document.file_name}}">Download</a>
<!-- download-template.html -->
<div ng-controller="DocumentCtrl">
<a ng-click="download(document)">Download</a>
</div>
// 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);
});
};
}]);
<a ng-href="/api/downloadFile/{{download.id}}" type="submit" class="btn btn-primary col-lg-12 btn-modal-costume" >download</a>
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");
}
$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);
});
};