如何通过nodejs通过Google Docs API提供pdf文件(不保存文件)?

时间:2019-05-24 22:58:58

标签: node.js express pdf google-docs-api google-api-nodejs-client

我试图通过Google Docs API通过Nodejs Express服务器提供PDF文件(在上下文中,这是一份简历)。我能够轻松地使用HTML,文本和rtf文件来完成此操作。我无法使用PDF和其他格式(例如zip,doc)来完成此操作(也许是因为它们是二进制文件类型)

macOS Mojave | nodejs v10.15.0 | express.js v4.17.0 | Chrome v74.0.3729.157


我最初设置了Google Docs API,并使用text / plain调用了drive.files.export函数,然后在res.send中传递了res​​ult.data(我的简历的纯文本版本的字符串)。这有效√

接下来,我做了同样的事情,但是我设置了头文件res.setHeader("Content-disposition", "attachment; filename=resume.txt");,并且再次起作用了;我可以在浏览器中下载文本文件。 √

我再次尝试了相同的操作,这次将“ application / rtf”传递给Google Docs API,然后在响应中设置了适当的标头,因此我能够获得简历的rtf版本。 √

在这里事情对我不起作用...

下一个合乎逻辑的步骤是对PDF进行相同的设置,就像我对RTF一样设置所有标题。下载的文件大小与我预期的差不多,并且在Node.js中没有出现任何错误,但是文件无效(无法在任何应用程序中打开)。我对.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文件。

0 个答案:

没有答案