指定如何处理文件下载都归结为Content-disposition
标题。您也可以在此处指定文件的名称。我们还设置了Content-type
以确保浏览器知道如何处理给它的文件。
Express.js 示例:
app.post('/url/to/hit', function(req, res, next) {
var stream = fs.readStream('/location/of/pdf');
var filename = "WhateverFilenameYouWant.pdf";
// Be careful of special characters
filename = encodeURIComponent(filename);
// Ideally this should strip them
res.setHeader('Content-disposition', 'inline; filename="' + filename + '"');
res.setHeader('Content-type', 'application/pdf');
stream.pipe(res);
});
现在,如果您更仔细地查看Content-disposition
,您会注意到该inline;
字段设置了浏览器对文件的反应方式。如果你想强制下载,你可以通过设置inline;
来做到这一点attachment;
我还发现(被烧了几次),如果您在文件名中设置特殊字符,它可能会损坏。所以我encodeURIComponent()
的文件名以确保不会发生。
希望能帮助其他人试图弄清楚同样的事情!
编辑
在我最初和现在发布此内容之间的时间里,我发现了如何正确编码content-disposition
's filename 参数。 根据规范,文件名应该是 RFC5987 编码的。 我最终从 MDN 中找到了一个示例代码片段,它可以正确处理此处的编码(encodeURIComponent()
这不是该字段的完全正确格式)。
MDN 片段
var fileName = 'my file(2).txt';
var header = "Content-Disposition: attachment; filename*=UTF-8''"
+ encodeRFC5987ValueChars(fileName);
console.log(header);
// logs "Content-Disposition: attachment; filename*=UTF-8''my%20file%282%29.txt"
function encodeRFC5987ValueChars (str) {
return encodeURIComponent(str).
// Note that although RFC3986 reserves "!", RFC5987 does not,
// so we do not need to escape it
replace(/['()]/g, escape). // i.e., %27 %28 %29
replace(/\*/g, '%2A').
// The following are not required for percent-encoding per RFC5987,
// so we can allow for a little better readability over the wire: |`^
replace(/%(?:7C|60|5E)/g, unescape);
}
在此之上的另一个注意事项是,浏览器也不完全符合规范。有些字符仍然会从下载中错误地返回(至少在我测试时)。
您可以通过更新下载的工作方式来解决此问题。如果您的下载 URL 以文件名结尾(并且您没有filename
在标头中提供属性),它将正确地从 URL 编码值中获取文件名。IE'http://subdomain.domain-url.com/some/path/to/downloads/' + encodeURIComponent("You're there, download this!.pdf")
Jeeze,以及所有为您的下载提供文件名!