node.js - 如何通过 nodejs 的 Google Docs API 提供 pdf 文件(不保存文件)?
问题描述
我正在尝试通过 Google Docs API 的 Nodejs Express 服务器提供 PDF 文件(对于上下文,它是一份简历)。我可以轻松地使用 HTML、文本和 rtf 文件完成此操作。我无法使用 PDF 和 zip、doc 等其他格式来完成此操作(可能是因为它们是二进制文件类型)
macOS 莫哈韦 | nodejs v10.15.0 | express.js v4.17.0 | 铬 v74.0.3729.157
我最初设置了 Google Docs API 并drive.files.export
使用 text/plain 调用了该函数,然后在 res.send 中传递了 result.data(我的简历的纯文本版本的字符串)。这有效 √</p>
接下来,我做了同样的事情,但我设置了 headers res.setHeader("Content-disposition", "attachment; filename=resume.txt");
,它再次起作用了;我可以在我的浏览器中下载一个文本文件。√</p>
我再次尝试了同样的事情,这次将“应用程序/rtf”传递给 Google Docs API,然后在我的响应中设置适当的标题,我能够获得我的简历的 rtf 版本。√</p>
这就是我停止工作的地方......
下一个合乎逻辑的步骤是对 PDF 做同样的事情,设置所有标题,就像我对 RTF 所做的那样。下载的文件大约是我期望的大小,并且我在 Nodejs 中没有收到任何错误,但该文件无效(无法使用任何应用程序打开)。我对 .doc、.zip 和其他一些文件进行了同样的尝试。没运气。
我读过一些文章,人们将数据通过管道传输到写入流中并将文件保存到他们的服务器。我不想这样做。
大多数其他资源都在解释如何从服务器上的公共文件夹下载公共 pdf 文件。也不是我所追求的。
当我从 Google Docs 控制台记录响应对象时,我得到一个对象,其中包含一堆请求标头和文件元数据,以及包含所有原始数据的“数据”对象。文本格式的数据看起来像预期的人类可读数据,而二进制格式的数据看起来像预期的乱码。
我最接近任何进展的是当我尝试使用 .zip 格式时,我能够下载一个我可以(只能)通过终端解压缩的 zip 存档,它会生成一个空白文件,但至少具有正确的名称。这可能是因为 zip 文件包含有关其包含的文件的纯文本说明,因此没有损坏。
RTF 文件的工作示例代码:
router.get("/rtf", (req, res) => {
const docData = googleapi.getGoogleDocs("application/rtf");
docData.then(dd => {
res.setHeader("Content-Type", "application/rtf");
res.setHeader("Content-Disposition", "attachment; filename=resume.rtf");
res.send(dd.data);
});
});
// ... some auth stuff, Promises, etc ...
getGoogleDocs(mimeType) {
return drive.files
.export({
fileId: "XxXxXxXxXxXxXxXxXxXxXxXxXxXxXx",
mimeType: mimeType
})
.then(fileData => {
return fileData;
});
}
我尝试了一些不同的方法来获得与 PDF 相同的成功。几乎所有组合都会导致下载的文件无效/损坏:
router.get("/pdf", (req, res) => {
const docData = googleapi.getGoogleDocs("application/pdf");
docData.then(dd => {
// Tried various headers:
res.setHeader("Content-Type", "application/pdf");
// res.setHeader("Content-Type", "application/octet-stream");
res.setHeader(
"Content-Disposition",
"attachment; filename=resume_html.zip"
);
// Setting the content length based on the meta-data from
// the Google Docs API payload
res.setHeader("Content-Length", "476");
// Tried various ways to send the response:
// res.setHeader("Content-Transfer-Encoding", "binary");
res.end(dd.data, "binary");
});
});
..以及围绕调用 Google Docs API 的修改代码...
const aPromise = new Promise((resolve, reject) => {
drive.files.export(
{
fileId: "XxXxXxXxXxXxXxXxXxXxXxXxXxXxXx",
mimeType: mimeType
},
{ encoding: null },
(err, buffer) => {
// There were no errors.
err ? reject(err) : resolve(buffer);
// return buffer;
}
);
});
return aPromise;
建议添加 'encoding: null' 作为防止损坏二进制数据的一种方法。鉴于数据位于字符串格式的响应对象中,我不确定这将有何帮助。
预期结果:我可以下载一个有效的 PDF 文件。
实际结果:我得到一个文件,其中包含从 Google Docs API 接收的数据,可能是原始 PDF 数据,但它不会导致下载有效/可识别的 pdf 文件。
解决方案
推荐阅读
- javascript - 多个 Firebase 功能不起作用
- c# - 如何在 GMap.NET 中使地图无限?
- flutter - 如何检查用户是向左还是向右滑动?
- xamarin.forms - Xamarin 表单 NU1202 和 NU1608 错误
- ios - 多行标签因位置约束而中断
- computer-vision - 从 Roll、Yaw、Pitch 和 GPS+Altitude 到 ECEF 转换矩阵的图像
- unreal-engine4 - 虚幻引擎 4 默认球体网格位置
- c - 将大数字作为字符串处理
- php - 致命错误:调用未定义的函数 runQuery()
- c# - protobuf3 中的重复 Int32Value(可为空的 int 数组)