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
属性。
- 总是下载 :如果你想要文件总是下载,你可以做的是在blob上设置
Content-Disposition
属性。 这样,每当有人访问blob,文件将永远被下载。 - 下载有时 :如果有时需要下载文件,而有时打开浏览器,则可以在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.... })