【问题标题】:AngularJS force Firefox/Safari to download file instead of opening in browserAngularJS 强制 Firefox/Safari 下载文件而不是在浏览器中打开
【发布时间】:2015-12-18 22:03:12
【问题描述】:

我有一个 PDF 文件,可以在除 Firefox/Safari 之外的所有浏览器上下载。它在浏览器窗口中打开它,而不是下载文件。我的站点在 node.js 之上运行并托管在 Azure 中。用户下载的文件来自 Azure blob 存储,所以我怀疑这可能是 CORS 问题。

这是我下载的客户端代码:

<a href="{{fileURL}}" class="btn btn-default" download="myfile.pdf">Download File</a>

这是服务器端代码:

$scope.fileURL = 'https://myblob.blob.core.windows.net/8282020/myfile.pdf';

更新:我可以通过根据下面的帮助在 Azure 中设置 blob 属性来添加内容配置,它显示配置为“附件”,但在 FireFox/Safari 中它仍然是在浏览器中打开。由于 Azure Blob 存储可能被视为 CORS,这是否可能被阻止?

更新 2: 将以下内容添加到我的 HTML 标记中似乎可以在 FireFox(但不是 Safari)中工作,这是跨浏览器处理此问题的正确方法

type="application/octet-stream"

更新 3: 通过 Node 设置内容配置和内容类型似乎可以正常工作。我不得不问,这是正确的方式吗?

blobSvc.setBlobProperties(containerName, filename, { contentDisposition: 'attachment', contentType: 'application/octet-stream' }, function (error, result, response) {
// result code here....
})

【问题讨论】:

  • 我已经有了下载标签,它适用于某些浏览器,但不适用于 Safari 和 Firefox
  • 您能否在为文件提供服务的响应中添加“Content-disposition: attachment”标头?
  • 很想这样做,但不确定我会在哪里这样做?节点? IIS?蔚蓝?

标签: node.js angularjs azure firefox


【解决方案1】:

一般情况下,我们可以将 blob 的 Content-Disposition 设置为 attachment,以指示用户代理不应显示响应,而是显示文件名不是指定的 blob 名称。 您可以参考Set Blob Properties了解更多信息。

我可以在初始上传时设置处置吗?我正在使用 Node/JavaScript:blobSvc.createBlockBlobFromLocalFile('mycontainer', 'myblob', 'test.txt', function(error, result, response){ if(!error){ // 文件上传 } });

在我的测试中,我必须setBlobProperties在Azure Storage中创建blob后,我才能成功设置blob的Content-Disposition。

例如

blobsrv.createBlockBlobFromLocalFile('mycontainer', 'Azure.pdf', 'upload/Azure.pdf', function (error, result, response) {

        if (error) res.send(500);
        blobsrv.setBlobProperties('mycontainer', 'Azure.pdf', { contentDisposition: 'attachment' }, function (error, result, response) {
            res.send(200, JSON.stringify(response));
        })
    });

在我的测试中,Angular 前端将下载文件,而不是直接在 FireFox 浏览器中打开它。

<a href="{{pdfurl}}" download="Azure.pdf">Azure.pdf</a>
$scope.pdfurl = "http://<cantainer>.blob.core.windows.net/mycontainer/Azure.pdf";

【讨论】:

  • 奇怪,它以附件形式显示内容配置,但在 Firefox 中它仍然在浏览器中打开而不是下载。
【解决方案2】:

您可以在为文件提供服务的响应中添加“Content-disposition: attachment”标头。由于您的文件存储在 Azure Blob 存储中,因此您将不得不通过您的节点应用代理请求。

所以原来的代码会改成这样的:

$scope.fileURL = '<your-node-app-address>/myfile.pdf';

和

<a href="{{fileURL}}" class="btn btn-default" download="myfile.pdf">Download File</a>

然后你将在你的节点应用程序中设置一个路由 &lt;your-node-app-address&gt;/myfile.pdf 并附加正确的标题,例如:

var client = restify.createStringClient({ 
        url: 'https://myblob.blob.core.windows.net'
    });    
client.get('/8282020/myfile.pdf', function(err, req, res, data) {
            response.setHeader('Content-Disposition', 'attachment');
            response.writeHead(res.statusCode);
            response.write(data);
            response.end();
        });

【讨论】:

  • restify 是 node 模块还是内置的?
  • 是的,它是一个内置的节点模块,但这只是示例代码。本质上,您只需要向您的 blob 发出另一个请求,并附加标头,这就是我想要解决的问题。
  • 如何找到我的节点应用地址? (可能我缺少一些基本的东西)
  • 如果它托管在同一个域上,那么您可以使用 $scope.fileURL = '/myfile.pdf';您只是将请求重新指向您的应用程序,以便您可以代理它并将标题附加到响应中。
  • 应该是,它是一个基于 Node.js 的 Angular 应用
【解决方案3】:

有两种方法可以在不通过您的网络服务器流式传输内容的情况下执行此操作,并且它们都涉及在 blob 本身上设置 Content-Disposition 属性。

  1. 始终下载:如果您希望文件始终下载,您可以在 blob 本身上设置 Content-Disposition 属性。这样,无论何时有人访问该 blob,该文件都会被下载。
  2. 有时下载:如果您希望有时在打开浏览器时有时下载文件,您可以在 blob 上创建一个至少具有Read 权限的Shared Access Signature (SAS) 并覆盖Content-Disposition当您想要下载文件时,SAS 中的响应标头。如果要在浏览器中打开文件,只需在 SAS 中省略此响应标头即可。

请在我的博客中阅读Overriding Commonly Used Headers in SAS:http://gauravmantri.com/2013/11/28/new-changes-to-windows-azure-storage-a-perfect-thanksgiving-gift/。

更新

但是如何在 Azure Blob 存储中设置内容处置?是 我可以使用一些东西在我的所有 blob 容器中设置一些东西 像 Azure 存储资源管理器?还是我需要为每个 blob 设置它/如何设置 我这样做?

这是您需要为容器中的每个 blob 执行的操作。您不能在容器级别执行此操作。我认为 Azure 存储资源管理器不支持此功能。在我正在构建的工具 (Cloud Portam - http://www.cloudportam.com) 中,我已经包含了这个功能,但是您必须再次为每个单独的 blob 执行此操作。其他替代方法是使用任何客户端 SDK 更新 blob 的属性。方法是列出容器中的 blob(应该为您提供 blob 属性),更新 ContentDisposition 属性并保存属性。

更新 2

我可以在初始上传时设置处置吗?我在用 节点/JavaScript:blobSvc.createBlockBlobFromLocalFile('mycontainer', 'myblob'、'test.txt'、函数(错误、结果、响应){ if(!error){ // 文件上传 } });

当然可以!在此处查看createBlockBlobFromLocalFile 的源代码:https://github.com/Azure/azure-storage-node/blob/master/lib/services/blob/blobservice.js。您可以通过在 options.contentDisposition 中提供适当的值来设置 content-diposition 属性。

【讨论】:

  • #1 可能是我正在寻找的。我阅读了您的博客(顺便说一句很棒),但是如何在 Azure Blob 存储中设置内容处置?这是我可以使用 Azure 存储资源管理器之类的东西在我的所有 blob 容器中设置的东西吗?还是我需要为每个 blob 设置它/我该怎么做?
  • 更新了我对您的 cmets 的回答。 HTH。
  • 我可以设置初始上传的配置吗?我正在使用 Node/JavaScript:blobSvc.createBlockBlobFromLocalFile('mycontainer', 'myblob', 'test.txt', function(error, result, response){ if(!error){ // 文件上传 } });跨度>
  • 更新了我对您评论的回复。 HTH。
【解决方案4】:

试试这个库http://danml.com/download.html 或https://developer.mozilla.org/en/docs/Web/API/File。

它们提供了一个 blob 接口。

【讨论】:

    【解决方案5】:

    通过 Node 设置内容配置和内容类型似乎是有效的。看来两者都需要。

    blobSvc.setBlobProperties(containerName, filename, { contentDisposition: 'attachment', contentType: 'application/octet-stream' }, function (error, result, response) {
    // result code here....
    })
    

    【讨论】:

      猜你喜欢
      • 2013-04-13
      • 2011-06-19
      • 2013-10-15
      • 2014-01-29
      • 1970-01-01
      • 2011-09-11
      相关资源
      最近更新 更多