从Amazon S3中提取PDF并直接在缓冲区/流

时间:2017-12-12 22:58:44

标签: javascript node.js amazon-s3

我有一个要求,即PDF不会保存在本地服务器上,而是私密存储在Amazon S3存储桶上。但根据具体要求,我需要检索PDF并直接在用户浏览器中呈现它,而无需在Web服务器上下载。

我能够在node.js中精确地提取流并使用PDF数据进行响应。当我检查Chrome开发工具中的响应数据时,它看起来像PDF数据,我甚至可以阅读文档中的文本。

let params = {Bucket: process.env.S3STORAGE, Key: req.query.fileName};
res.attachment(req.query.fileName);
s3.getObject(params).createReadStream().pipe(res);

我已尝试过多种方法来正确渲染它。它要么显示空白PDF,要么显示gobbly gook PDF数据。

我正在使用vue2模板,并试图在bootstrap模式中弹出PDF。在这次尝试中,我得到一个空白的PDF:

<object :data="pdfStream" type="application/pdf" width="800px" :height="browserHeight"></object>


this.pdfStream = response.bodyText;

我看到一些答案说base64对它进行了编码,但仍然无法使其工作。

// server side
let params = {Bucket: process.env.S3STORAGE, Key: req.query.fileName};
s3.getObject(params).createReadStream().pipe(strs('binary', 'base64')).pipe(res);

然后

//client side
 let objbuilder = '';
        objbuilder += ('<object width="100%" height="100%" data="data:application/pdf;base64,');
        objbuilder += (response.bodyText);
        objbuilder += ('" type="application/pdf" class="internal">');
        objbuilder += ('<embed src="data:application/pdf;base64,');
        objbuilder += (response.bodyText);
        objbuilder += ('" type="application/pdf"  />');
        objbuilder += ('</object>');
        this.pdfStream = objbuilder;

当然,我错过了一些简单的事情,或者犯了一个愚蠢的错误,但不确定它是什么。我一直只提供实际文件,但在这个特定实例中,目标是直接将数据呈现到浏览器中,而不生成位于S3存储中的PDF副本。

更新

杰森的回答指出了我正确的方向,我相信我现在正走在正确的轨道上。然而,我不确定它是否会抛出错误。

我的第一次尝试就是:

// returning a base64 encoded PDF from Amazon to the client
let params = {Bucket: process.env.S3STORAGE, Key: req.query.fileName};
s3.getObject(params).createReadStream().pipe(strs('binary', 'base64')).pipe(res);

然后在客户端Vue组件:

//import PDFJS from 'pdfjs-dist';
export default {
  {components: PDFJS},
  ...
  ...

  ...
  viewDocument(fileName, documentName) {

      this.$http.get('/fetchDocument', {
        params: {
          fileName: fileName
        }
      })
      .then(response => {

         PDFJS.getDocument(response.bodyText).then(function (pdfDocument) {

          console.log('Number of pages: ' + pdfDocument.numPages);

        });
      });

    },

它回击了这个错误:

app.js:58668 GET http://192.168.3.14:3000/dist/app.worker.js net::ERR_ABORTED
app.js:55073 Warning: Setting up fake worker.
app.js:104 GET http://192.168.3.14:3000/0.js net::ERR_ABORTED
app.js:99 Uncaught (in promise) Error: Loading chunk 0 failed.
    at HTMLScriptElement.onScriptComplete (app.js:99)

pdfjs-dist库中没有app.worker.js0.js

然后......如果我从节点返回没有base64的原始方式,它返回的原始PDF流开始如下:

%PDF-1.2
%����
3 0 obj
<< 
/Lineariz

我得到一个完全不同的错误

Uncaught (in promise) TypeError: Failed to construct 'URL': Invalid URL

最后,我在here上尝试了base64Uint8Array函数对节点返回的base64编码数据的影响,这导致了我刚收到的app.worker.js和0.js 404错误。

pdfjs-dist软件包没有那些js文件,因此不确定究竟发生了什么。

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

您需要使用渲染器将PDF数据渲染到浏览器中。其中一个项目是Mozilla的PDF.JS project。由于您使用的是vue,因此您可以查看此示例的用法:https://github.com/shershen08/vue2-pdfjs-viewer

浏览器已经内置了PDF阅读器,但不是在JS应用程序的上下文中。这就是PDF.JS项目进入图片的地方。