【问题标题】:Download text/csv content as files from server in Angular在 Angular 中从服务器下载文本/csv 内容作为文件
【发布时间】:2014-01-21 03:39:38
【问题描述】:

我正在尝试从 node.js 服务器流式传输 csv 文件。服务器部分非常简单:

server.get('/orders' function(req, res) {
  res.setHeader('content-type', 'text/csv');
  res.setHeader('content-disposition', 'attachment; filename='orders.csv');
  return orders.pipe(res); // assuming orders is a csv file readable stream (doesn't have to be a stream, can be a normal response)
}

在我的角度控制器中,我正在尝试做这样的事情

$scope.csv = function() {
    $http({method: 'GET', url: '/orders'});
};

在我看来,当单击带有ng-click 的按钮时调用此函数:

<button ng-click="csv()">.csv</button>

我查看了有关从 Angular 中的服务器下载文件的其他答案,但没有找到任何对我有用的东西。有没有一种通用的方法可以做到这一点?看起来应该很简单。

【问题讨论】:

  • 首先我可以看到您在$scope.csv 中的网址与您在server.get 中的网址不符
  • @dcodesmith 忽略 please (fixed) 只是为了这个问题。我实际上确实在服务器上看到了请求

标签: javascript node.js angularjs http http-headers


【解决方案1】:

$http 服务返回一个promise,它有两个回调方法,如下所示。

$http({method: 'GET', url: '/someUrl'}).
  success(function(data, status, headers, config) {
     var anchor = angular.element('<a/>');
     anchor.attr({
         href: 'data:attachment/csv;charset=utf-8,' + encodeURI(data),
         target: '_blank',
         download: 'filename.csv'
     })[0].click();

  }).
  error(function(data, status, headers, config) {
    // handle error
  });

【讨论】:

  • 这并不能解决我的问题,因为它只是将文件内容打印到控制台。我需要以某种方式告诉它让浏览器处理下载...
  • 它虽然以一种骇人听闻的方式起作用:首先 chrome 的弹出窗口阻止程序阻止了点击,然后当我允许弹出窗口时,它在新窗口中打开了下载。有没有让它更愉快?如果没有,我想这对我来说已经足够了:)
  • 在 Mozilla Firefox 上不工作...在 Chrome 中工作正常。
  • 要让它在 Mozilla Firefox 上运行,请将锚附加到文档:angular.element(document.body).append(anchor);
  • stackoverflow.com/a/35448277/3366706 适用于 IE 11 和 chrome
【解决方案2】:

大多数关于此问题的references on the web 都指出您无法通过“开箱即用”的 ajax 调用下载文件。我已经看到涉及iframes 的(hackish)解决方案以及像@dcodesmith 这样的解决方案,它们可以工作并且完全可行。

这是我发现的另一个解决方案,它适用于 Angular 并且非常简单。

视图中,用&lt;a&gt;标签包裹csv下载按钮,如下所示:

<a target="_self" ng-href="{{csv_link}}">
  <button>download csv</button>
</a>

(请注意那里的target="_self,在ng-app 中禁用Angular 的路由至关重要here

在你的controller中,你可以通过以下方式定义csv_link

$scope.csv_link = '/orders' + $window.location.search;

$window.location.search 是可选的,如果您想将额外的搜索查询传递给您的服务器,则仅此选项)

现在每次单击按钮时,它都应该开始下载。

【讨论】:

  • 如果我们需要将一些大对象发布到服务器并获取生成的 word/pdf 文件,有什么方法可以做到这一点?
  • @ShivKumar 是的,响应 POST 请求,将 URL 返回到 csv。
  • 你能用完整的控制器和 UI 代码设置 JSFiddle 吗?
  • 这个解决方案与一个简单的 标签并没有什么不同,带有由角度评估的 href。
【解决方案3】:
var anchor = angular.element('<a/>');
anchor.css({display: 'none'}); // Make sure it's not visible
angular.element(document.body).append(anchor); // Attach to document

anchor.attr({
    href: 'data:attachment/csv;charset=utf-8,' + encodeURI(data),
    target: '_blank',
    download: 'filename.csv'
})[0].click();

anchor.remove(); // Clean it up afterwards

此代码适用于 Mozilla 和 chrome

【讨论】:

  • 感谢您的回答。这个确实适用于 Chrome 和 Firefox。
  • 每个浏览器的哪个版本?
  • 这是天才。该技术可用于从 angular 文件中下载任意数据。
  • 什么是IE版本?
  • 在 Firefox 和 chrome 中运行良好,但在 safari 中无法运行
【解决方案4】:

这对我来说适用于 IE 11+、Firefox 和 Chrome。在 safari 中,它会下载一个文件,但未知且文件名未设置。

if (window.navigator.msSaveOrOpenBlob) {
    var blob = new Blob([csvDataString]);  //csv data string as an array.
    // IE hack; see http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx
    window.navigator.msSaveBlob(blob, fileName);
} else {
    var anchor = angular.element('<a/>');
    anchor.css({display: 'none'}); // Make sure it's not visible
    angular.element(document.body).append(anchor); // Attach to document for FireFox

    anchor.attr({
        href: 'data:attachment/csv;charset=utf-8,' + encodeURI(csvDataString),
        target: '_blank',
        download: fileName
})[0].click();
anchor.remove();
}

【讨论】:

    【解决方案5】:

    使用角度 1.5.9

    我通过将 window.location 设置为 csv 文件下载 url 使它像这样工作。经过测试,可与最新版本的 Chrome 和 IE11 配合使用。

    角度

       $scope.downloadStats = function downloadStats{
            var csvFileRoute = '/stats/download';
            $window.location = url;
        }
    

    html

    <a target="_self" ng-click="downloadStats()"><i class="fa fa-download"></i> CSV</a>
    

    php 中为响应设置以下标头:

    $headers = [
        'content-type'              => 'text/csv',
        'Content-Disposition'       => 'attachment; filename="export.csv"',
        'Cache-control'             => 'private, must-revalidate, post-check=0, pre-check=0',
        'Content-transfer-encoding' => 'binary',
        'Expires' => '0',
        'Pragma' => 'public',
    ];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-26
      • 1970-01-01
      • 2018-11-13
      • 1970-01-01
      相关资源
      最近更新 更多