node.js - 在快速路由响应中发送 PDF 并强制浏览器下载
问题描述
背景
我正在快速服务器上生成 PDF 并将其保存到本地目录。在回调中,我试图将 PDF 发送回服务器,以便下载,但它出现在网络选项卡响应中,因为它似乎是二进制文件并且不下载。
例子
编辑我的客户端函数发出服务器请求 此 fetch 调用到达一个应返回 PDF 的快速端点。特快路线如下,
function setImage() {
html2canvas(document.querySelector('#chart')).then(canvas => {
canvas.toBlob(
function(blob) {
const url = 'http://localhost:3000/api/v1/pdf';
fetch(url, {
method: 'POST',
headers: {
'Content-type': 'application/octet-stream',
},
body: blob,
})
.then(response => response.json())
.then(success => console.log(success))
.catch(error => console.log(error));
},
'image/png',
1,
);
document.body.appendChild(canvas);
});
}
//创建 PDF 并将其保存在服务器上的 filePath
router.post('/', (req, res, next) => {
pdf.create(html, options).toFile(filePath, err => {
if (err) {
return console.log(err);
}
const stat = fs.statSync('./downloads/report.pdf');
res.contentType('application/pdf');
res.setHeader('Content-Length', stat.size);
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Content-Disposition', 'attachment; filename=report.pdf');
// *Should force download the file to the browser*
res.download('../downloads/report.pdf', 'report.pdf', function(e) {
if (e) {
// Handle error, but keep in mind the response may be partially-sent
// so check res.headersSent
} else {
// It worked, do something else.
}
});
});
});
编辑我也在服务器上试过这个,它在浏览器中显示响应,但不会下载文件。
router.post('/', (req, res, next) => {
const img = req.body;
const filepath = 'uploads/chart.png';
fs.writeFile(filepath, img, err => {
if (err) {
throw err;
}
console.log('The file was succesfully saved!');
});
const html = tmpl.replace('{{chart}}', `file://${require.resolve('../uploads/chart.png')}`);
const options = { format: 'Letter' };
const fileName = 'report.pdf';
const filePath = './downloads/report.pdf';
pdf.create(html, options).toFile(filePath, err => {
if (err) {
return console.log(err);
}
const stat = fs.statSync('./downloads/report.pdf');
res.setHeader('Content-Description', 'File Transfer');
res.setHeader('Content-Length', stat.size);
res.setHeader('Content-type', 'application/octet-stream');
res.setHeader('Content-type', 'application/pdf');
res.setHeader('Content-Type', 'application/force-download');
res.setHeader('Content-disposition', 'attachment;filename=report.pdf');
res.sendFile('/downloads/report.pdf');
});
浏览器中的输出示例
问题
Express 4中强制浏览器下载PDF的正确方法是什么?
解决方案
我现在看到您的问题,fetch 使用 AJAX 在后台发出请求,响应转到您的代码,然后您捕获它并将其作为 JSON 写入屏幕。为了打开文件对话框并下载文件,您需要有一个指向相同位置的链接,<a href=....>
或者您可以尝试此处建议的
内容如何使用 window.fetch 下载文件?
推荐阅读
- ssis - 如何在事实表中插入 ID
- python - 如何检测我的 Tkinter 窗口是否有焦点?
- ruby-on-rails - SQLite3::SQLException: 没有这样的表
- java - Eclipse 2019-12 显示错误:不支持 JRE Private Build/14.0.1,禁用高级源查找
- laravel - Laravel 500 问题
- c++ - 在 C++ 中使用 while 循环查找下一个素数的简单函数
- javascript - 在 express/REST 中访问数组组件
- python - 为什么我的一个函数在不应该的时候只是循环回来?
- javascript - JS:添加日期对象数组
- python - 如何更改使用 exec() 函数创建的 tkinter 小部件的配置