2015-12-18 144 views
7

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

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

<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:通过节点设置内容配置和内容类型似乎正在工作。我必须问,这是正确的方法吗?

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

这可能是有用的http://stackoverflow.com/questions/11353425/force-a-browser-to-save-file-as-after-clicking-link –

+0

我已经有下载标签,它在一些浏览器而不是Safari和Firefox – Kode

+0

您可以向服务该文件的响应添加“Content-disposition:attachment”标头吗? – theadriangreen

回答

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(); 
     }); 
+0

是否考虑节点模块或内置? – Kode

+1

是的,它是一个内置的节点模块,但这只是示例代码。基本上,你只需要向你的blob发出另一个请求,并附上标题,这正是我试图解决的问题。 – theadriangreen

+0

我如何找到我的节点应用程序地址? (可能是我缺少的基本信息) – Kode

1

有两种方法可以做到这一点通过您的Web服务器流出内容,并且它们都涉及在Blob本身上设置Content-Disposition属性。

  1. 随时下载:如果你想要的文件总是下载,你可以做的是设置在BLOB本身Content-Disposition财产。这样,每当有人访问blob时,该文件将始终被下载。
  2. 下载有时:如果你想有时下载,而有时打开浏览器中的文件,你可以做的是与至少Read权限团块创建Shared Access Signature (SAS)并覆盖Content-Disposition响应头在SAS,当你想下载文件。如果您想在浏览器中打开该文件,只需在SAS中省略此响应头。

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

UPDATE

但我怎么设置在Azure的Blob存储的内容处置?是 ,我可以使用类似Azure存储浏览器的东西 在我的所有blob容器中设置一些东西?或者我需要设置每blob/ 我这样做?

这是您需要为容器中的每个blob执行的操作。您无法在容器级别执行此操作。我不认为Azure存储浏览器支持这种功能。在我正在构建的工具(Cloud Portam - http://www.cloudportam.com)中,我已经包含了这个功能,但是您必须为每个单独的blob执行此操作。另一种方法是使用任何客户端SDK更新blob的属性。该方法将列出一个容器中的斑点(它应该给你blob属性),更新ContentDisposition属性并保存属性。

更新2

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

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

+0

#1可能是我正在寻找的。我读过您的博客(顺便说一下),但是如何在Azure Blob存储中设置内容处置?这是我可以使用Azure存储浏览器之类的所有blob容器来设置的东西吗?或者我需要将它设置为每个blob /我将如何做到这一点? – Kode

+0

更新我的回复并回复您的评论。 HTH。 –

+0

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

2

一般情况下,我们可以设置BLOB的内容处置attachment,表明用户代理不应该显示的反应,而是表明一个另存为比指定的BLOB名以外的文件名对话框。 有关更多信息,请参阅Set Blob Properties

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

在我的测试,我不得不setBlobProperties创造了Azure存储的斑点,我会成功的设置BLOB的Content-Disposition后。

E.G.

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"; 
+0

奇怪的是,它显示内容配置为附件,但在Firefox中它仍然在浏览器中打开而不是下载。 – Kode

0

通过节点设置内容配置和内容类型似乎正在工作。看起来两者都是需要的。

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