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

我有一个PDF文件,可以在除Firefox / Safari以外的所有浏览器中下载。 它会在浏览器窗口中打开它,而不是下载该文件。 我的网站运行在node.js之上,并在Azure中托pipe。 用户下载的文件来自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:通过节点设置内容configuration和内容types似乎正在工作。 我必须问,这是正确的方法吗?

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

通常,我们可以将blob的Content-Disposition设置为attachment以指示用户代理不应该显示响应,而是显示另存为对话框,其名称不是指定的blob名称。 您可以参考设置Blob属性获取更多信息。

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

在我的testing中,我必须在Azure存储中创buildblob后设置setBlobProperties ,我将成功设置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的前端会下载文件,而不是直接在我的testing中的FireFox浏览器中打开它。

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

您可以将“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> 

然后你可以在你的节点应用程序中设置一个path,在<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(); }); 

有两种方法可以做到这一点,而不需要通过Web服务器stream式传输内容,而且这两种方法都需要在Blob本身上设置Content-Disposition属性。

  1. 总是下载 :如果你想要文件总是下载,你可以做的是在blob上设置Content-Disposition属性。 这样,每当有人访问blob,文件将永远被下载。
  2. 下载有时 :如果有时需要下载文件,而有时打开浏览器,则可以在blob上创build一个至less具有Read权限的Shared Access Signature (SAS) ,并覆盖SAS中的Content-Disposition响应头你想下载文件。 如果您想在浏览器中打开文件,只需在SAS中省略此响应头。

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

UPDATE

但是如何在Azure Blob存储中设置内容处置? 这是我可以使用类似Azure存储浏览器的所有blob容器设置的东西吗? 或者我需要设置它blob /我将如何做到这一点?

这是您需要为容器中的每个blob执行的操作。 你不能在容器层面上做到这一点。 我不认为Azure存储资源pipe理器支持这个function。 在我正在构build的工具(Cloud Portam – http://www.cloudportam.com )中,我已经包含了这个function,但是对于每个blob,您都必须这样做。 另一种方法是使用任何客户端SDK来更新blob的属性。 方法是列出一个容器中的blob(它应该给你blob属性),更新ContentDisposition属性并保存属性。

更新2

我可以设置初始上传的处置吗? 我使用Node / 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属性。

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

他们提供了一个blob接口。

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

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