首页 > 解决方案 > 如何通过 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 文件。

标签: node.jsexpresspdfgoogle-docs-apigoogle-api-nodejs-client

解决方案


推荐阅读