我的用户有私有(private)文件需要由经过身份验证的用户下载。我的服务器首先使用它自己的 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 拦截器无法捕获这种类型的外部链接点击,因此不会为服务器端身份验证附加适当的 header 。结果是 401 未经授权的错误。
相反,我需要使用 ng-click 触发下载,然后从 Angular Controller 执行 $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 保存文件的简单库(显然是在客户端)。
这让我通过了身份验证问题,但导致文件以不可读/不可用的格式保存/下载到客户端。
为什么下载的文件格式不可用?
提前致谢。
最佳答案
Angular 的 $http 方法需要配置为接受二进制数据响应。
Rails'send_data文档:
Sends the given binary data to the browser. This method is similar to render plain: data, but also allows you to specify whether the browser should display the response as a file attachment (i.e. in a download dialog) or as inline data. You may also set the content type, the apparent file name, and other things.
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可能比以下更具描述性:
Usage
$http(config);
Arguments
config
responseType - {string} - see XMLHttpRequest.responseType.
关于javascript - 使用 $http.get() 通过 Angular 下载远程文件 - OAuth 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36991167/