NodeJS - 如何从 Base64 返回 PDF 而不将文件保存在服务器上?

Mat*_*eus 8 pdf file fs node.js

这是我的场景:

  • 我有一个使用 Express 在 Node 中构建的应用程序;
  • 我有一个返回 Base64 PDF 文件的外部 API;
  • 我必须获取这个 Base64 并为用户打开该文件;
  • 我无法将 PDF 保存到服务器上。

我尝试了很多方法,但无法向用户打开该文件。

我尝试过的方法:

const buff = Buffer.from(myBase64, 'base64');
const file = fs.writeFileSync('boleto.pdf', buff, { encoding: 'base64' });

try {
  res.setHeader('Content-Length', file.size);
  res.setHeader('Content-Type', 'application/pdf');
  res.setHeader('Content-Disposition', 'attachment; filename=boleto.pdf');
} catch (e) {
  return res.status(404).send({ error: e, message: 'File does not exist.', statusCode: 404 });
}
Run Code Online (Sandbox Code Playgroud)
const buff = Buffer.from(myBase64, 'base64');
const file = fs.writeFileSync('boleto.pdf', buff, { encoding: 'base64' });

try {
  res.contentType('application/pdf');
  return res.status(200).sendFile('boleto');
} catch (e) {
  return res.status(404).send({ error: e, message: 'File does not exist.', statusCode: 404 });
}
Run Code Online (Sandbox Code Playgroud)
const buff = Buffer.from(myBase64, 'base64');
const file = fs.readFileSync(buff, { encoding: 'base64' });

try {
  res.contentType('application/pdf');
  return res.status(200).sendFile(file);
} catch (e) {
  return res.status(404).send({ error: e, message: 'File does not exist.', statusCode: 404 });
}
Run Code Online (Sandbox Code Playgroud)

有人能帮我吗?

Ste*_*las 8

此处执行此操作的正确方法是调用服务并将 Base64 字符串响应定向到解码流,然后通过管道将其传输到响应输出。这将使您不必等待文件下载或string->byte翻译完成。

但是,如果您只处理小文件(<1MB)并且不必处理来自数千个并发请求的流量,那么只需下载 Base64 字符串并Buffer.from(base64str, 'base64')在继续传递之前对其进行解码可能就可以了。

这种“最小实现”方法是这样的:

const axios = require('axios'); // or any other similar library (request, got, http...)

const express = require('express');
const router = express.Router();

router.get('/invoice/:id.pdf', async (req, res) => {
  // Here is the call to my external API to get a base64 string.
  const id = req.params.id;
  const response = await axios.get('https://myfileapi.domain.com/file/?id=' + id);
  const base64str = response.data;

  // Here is how I get user to download it nicely as PDF bytes instead of base64 string.
  res.type('application/pdf');
  res.header('Content-Disposition', `attachment; filename="${id}.pdf"`);
  res.send(Buffer.from(base64str, 'base64'));
});

module.exports = router;
Run Code Online (Sandbox Code Playgroud)

请注意,这里没有身份验证来阻止其他用户访问此文件,如果您需要身份验证,则必须单独处理。