我的问题源于这样一个事实,即我不能只使用 Express 中的 res.sendFile() 或 res.download(),因为浏览器 URL 栏没有访问路由,而是我的应用程序使用客户端路由,因此我必须通过 Fetch 或 XMLHttpRequest 发出 HTTP GET 请求。
第二个问题是我需要根据从客户端发送的 HTML 字符串在服务器上构建 PDF 文件 - 所以我需要再次发送请求正文的 GET 请求。
然后,我使用 Fetch 的解决方案是从客户端发出 Get 请求:
fetch('/route' , {
method: 'GET',
body: 'My HTML String'
});
在服务器上,我的代码使用 HTML-PDF 节点模块将 HTML 字符串转换为 PDF,然后我将该文件转换为 Base64 字符串,设置 MIME 类型并附加 data:application/pdf;base64,。
app.get('/route', (req, res) => {
// Use req.body to build and save PDF to temp storage (os.tempdir())
// ...
fs.readFile('./myPDF.pdf', (err, data) => {
if (err) res.status(500).send(err);
res.contentType('application/pdf')
.send(`data:application/pdf;base64,${new Buffer.from(data).toString('base64')}`);
});
});
回到客户端,我收到了前面提到的 Fetch Request,这意味着我只需要兑现承诺即可获得响应:
fetch('/route', {
method: 'POST',
body: 'My HTML String' // Would define object and stringify.
})
.then(res => res.text())
.then(base64String => {
// Now I just need to download the base64String as a PDF.
});
为了进行下载,我动态创建了一个锚标记,将其href 属性设置为来自服务器的响应中的 Base64 字符串,给它一个标题,然后以编程方式单击它:
const anchorTag = document.createElement('a');
anchorTag.href = base64String;
anchorTag.download = "My PDF File.pdf";
anchorTag.click();
所以,大家一起在客户端:
fetch('/route', {
method: 'POST',
body: 'My HTML String' // Would define object and stringify.
})
.then(res => res.text())
.then(base64String => {
const anchorTag = document.createElement('a');
anchorTag.href = base64String;
anchorTag.download = "My PDF File.pdf";
anchorTag.click();
});
使用锚标记触发下载的解决方案来自另一个 StackOverflow 答案。同样重要的是要注意 Base64 编码不是很有效。存在更好的解决方案,但就我而言,Base64 可以正常工作。
还必须注意 Base64 编码正是 - 一个编码方案,不是,我重复一遍,不是一个加密方案。因此,如果您的 PDF 文件包含特权信息,您可能希望将令牌身份验证添加到端点并加密文件。