【问题标题】:Download Remote File With Angular Using $http.get() - OAuth Authentication使用 $http.get() 使用 Angular 下载远程文件 - OAuth 身份验证
【发布时间】:2016-05-02 20:33:02
【问题描述】:

我的用户有需要由经过身份验证的用户下载的私人文件。我的服务器首先使用它自己的 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 保存文件的简单库(显然是在客户端上)。

这让我通过了身份验证问题,但导致文件以不可读/不可用的格式保存/下载到客户端。

为什么下载的文件格式不可用?

提前致谢。

【问题讨论】:

  • 您必须使用 FileSaver 吗?你试过window.navigator.msSaveOrOpenBlobwindow.open(objectUrl)吗?
  • 我不需要使用 FileSaver,但使用 window.navigator.msSaveOrOpenBlob 和 window.open(objectUrl) 都会导致相同的问题:不可读的文件格式。包装/构造的文件仍然被 Blob 再次包装/构造的情况。

标签: javascript ruby-on-rails angularjs amazon-s3 oauth


【解决方案1】:

Angular 的 $http 方法需要配置为接受 二进制数据 响应。

Rails 的send_data 文档:

将给定的二进制数据发送到浏览器。这种方法类似于 render plain:数据,还可以让你指定是否浏览器 应将响应显示为文件附件(即在下载中 对话框)或作为内联数据。您还可以设置内容类型, 明显的文件名和其他内容。

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

【讨论】:

    【解决方案2】:

    您好,我有一个示例,说明如何使用 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看到所有代码

    【讨论】:

    • 嗨 Ariel,感谢您的回复,但 download 仍然绕过 Angular 的 $http 拦截器,因此跳过身份验证。
    • 在我的代码中,我使用了 restAngular ,但在文件下载的情况下,我必须以这种方式使用它,因为如果不是这样,它会将文件作为后台请求返回,并且不会下载它。或者您只需要为 GET 请求和下载移动到新的 url。
    【解决方案3】:

    我认为您在使用 javascript 解决方案方面走在了正确的轨道上,但只是有一个错字。在$http.get 调用中,您传递一个空对象作为第二个参数。这是带有{responseType: arraybuffer} 的选项参数应该消失的地方。在此处查看 $http.get 的文档: https://docs.angularjs.org/api/ng/service/$http#get

    【讨论】:

      猜你喜欢
      • 2017-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-25
      • 2010-11-24
      • 2018-12-11
      • 1970-01-01
      相关资源
      最近更新 更多