AngularJS强制Firefox / Safari下载文件而不是在浏览器中打开

时间:2015-12-18 22:03:12

标签: angularjs node.js firefox azure cors

我有一个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属性来添加内容处置,并且它会将处置显示为&#34;附件&#34;但在FireFox / Safari中,它仍然在浏览器中打开。这可能被阻止,因为Azure Blob存储可能被视为CORS吗?

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

type="application/octet-stream"

更新3:通过节点设置内容处置和内容类型似乎正在运行。我不得不问,这是正确的方法吗?

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

4 个答案:

答案 0 :(得分:1)

您可以为提供文件的响应添加“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>

然后,您将在<your-node-app-address>/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();
        });

答案 1 :(得分:1)

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

  1. 始终下载:如果您希望文件始终下载,您可以执行的操作是在blob上设置Content-Disposition属性。这样,只要有人访问blob,就会始终下载该文件。
  2. 有时下载:如果您希望在打开浏览器时有时下载文件,您可以在Blob上创建Shared Access Signature (SAS)至少{{1}如果要下载文件,请在SAS中权限并覆盖Read响应标头。如果要在浏览器中打开文件,只需在SAS中省略此响应标题。
  3. 请在我的博客中阅读Content-Dispositionhttp://gauravmantri.com/2013/11/28/new-changes-to-windows-azure-storage-a-perfect-thanksgiving-gift/

    <强>更新

      

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

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

    更新2

      

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

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

答案 2 :(得分:1)

答案 3 :(得分:0)

通过Node设置内容配置和内容类型似乎正在运行。似乎两者都是必需的。

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