【问题标题】:How to handle file download errors with angularjs?如何使用 angularjs 处理文件下载错误?
【发布时间】:2014-05-24 18:47:46
【问题描述】:

下载文件看起来很简单,而且有很多可行的解决方案。 一直工作到服务器说401 UNAUTHORIZED我的要求很自然:

  • 在任何情况下都不能替换当前窗口。
  • 我不想打开新窗口,因为它没有任何意义。
  • 如果出现错误,必须向用户显示一些消息。

我尝试使用iframe 作为链接的目标,并希望在出现错误时得到通知。我看我很天真。

  • 我可以想象在 iframe 中放置一些脚本来通知主页onunload。它看起来有点复杂,所以我先问一下。
  • 我可以向服务器询问结果。不知何故,这肯定会奏效。但这也很复杂,因为有时间问题,并且会话已过期,所以我不得不绕过这个。

【问题讨论】:

  • 你试过Blob下载文件的网址吗?
  • @OnurYıldırım 不,从未听说过它们。从我刚刚阅读的内容来看,我相当怀疑。你能详细说明一下吗?
  • 当然。请看下面我的回答。

标签: javascript angularjs iframe download


【解决方案1】:

您可以使用Blob 对象来触发从javascript 下载文件。这是由 File API 引入的,并且仍处于 Working Draft 状态。 因此,您将获得有限的浏览器支持。截至 2015 年,您拥有对 Blob URLsBlob Constructor 的广泛浏览器支持。

<div ng-controller="appController" ng-app="app">
    <a ng-href="{{ fileUrl }}" download="file.txt">download</a>
</div>
var app = angular.module('app', []);

// Angular prepends "unsafe" tag in ng-href to prevent XSS
// so we need to sanitize this
app.config(['$compileProvider', function ($compileProvider) {
    // for Angular 1.0.x and 1.1.x, you should use urlSanitizationWhitelist
    $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|blob|ftp):/);
}]);

app.controller('appController', function ($scope, $window) {
    // Creating a Blob with our data for download
    // this will parse the URL in ng-href such as: blob:http...
    var data = 'some data here...',
        blob = new Blob([data], { type: 'text/plain' }),
        url = $window.URL || $window.webkitURL;
    $scope.fileUrl = url.createObjectURL(blob);
});

查看demo fiddle here

有一些库可以扩展浏览器对此的支持,例如Blob.js

您还应该查看FileSaver.js,它也回退到data:URI

【讨论】:

  • 效果很好。我用/^\s*(blob|https?|ftp|mailto|tel|file):/) 替换了您的正则表达式,它只是将“blob”添加到白名单中。您带有(|blob|) 的正则表达式看起来很奇怪。
  • 谢谢。我的生产代码中有https?|blob|ftp。删除了其余部分以使其简单..在上面修复它。
  • @OnurYıldırım:对不起,我不明白。这如何解决服务器响应 401 时报错的问题?这种方法似乎假设数据已经在客户端中。我错过了什么吗?
  • @ExpertSystem,请查看问题的 cmets 和其他答案。 OP 说 “我看不出如何让浏览器下载我通过 $http 加载的文件。” 使用这种方法,您可以在将数据作为下载提供之前处理错误.
  • @OnurYildirim:我明白了。因此,我们的想法是通过$http(处理任何错误)获取文件的内容,并使用您的方法启用作为文件下载。这是有道理的,谢谢澄清。这也适用于非文本文件吗?例如。以这种方式下载 PDF 或 XLSX 需要什么?
【解决方案2】:

您可以通过使用 HTTP 拦截器来处理 HTTP 错误,而不会中断您的控制器/服务逻辑。当错误发生时,在拦截器中处理它,然后将错误广播到错误处理程序,错误处理程序可以向用户显示错误。

$httpProvider.interceptors.push(function($q, dependency1, dependency2) {
    return {
       'request': function(config) {
        // same as above
        },

        'response': function(response) {
        // same as above
     }
  };

});

【讨论】:

  • 恐怕,我已经试过了。问题在于它不是$http 请求,而是由浏览器在单击&lt;a href=... download&gt; 时启动的单独的HTTP 请求。我看不到如何使浏览器 download 成为我通过 $http 加载的文件。
猜你喜欢
  • 2020-09-06
  • 1970-01-01
  • 2017-07-10
  • 2017-11-16
  • 1970-01-01
  • 2015-05-05
  • 2016-12-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多