【问题标题】:Send PDF from Server to Client将 PDF 从服务器发送到客户端
【发布时间】:2021-02-15 03:25:18
【问题描述】:

我正在尝试从 Google 云端硬盘访问 pdf。无论此访问权限是下载还是查看,都无所谓,它只需要可用即可。

我正在使用 Javascript 和 NodeJS,以及 express 和 google drive api。

我有以下下载 pdf 的功能。但愚蠢的我认为这是正确的,因为它在本地工作。然后当我部署它时,我意识到目标文件路径不再有意义。

function downloadDoc (sourceID, targetName, callback) {
  const dest = fs.createWriteStream(`${os.homedir()}/downloads/`+targetName);
  drive.files.get(
    {sourceID, alt: 'media'},
    {responseType: 'stream'},
    (err, res) => {
      if (err) {
        console.error(err);
      }
      res.data.on('end', () => {
        console.log('Done downloading file.');
        callback();
      })
       .on('error', err => {
          console.error('Error downloading file.');
          throw err;
        })
        .pipe(dest);
    });
}

所以我需要做的是,从这个函数中获取数据(或响应?)并将其发送到客户端。我认为这很容易做到,但是,作为一个简单的人,我发现自己陷入了困境。我写了这个,目的是让用户可以点击客户端的链接,请求这个 URL 并调用函数来下载 pdf。

app.get('/download_pdf', (req, res) => {
    downloadDoc(documentID, 'docName.pdf', ()=>{ 
      console.log("downloaded pdf");
    });
    res.end();
});

我想我需要更改提供给 pipe() 的参数,因为显然我不能使用文件路径。

我检查过的类似问题:
Display Pdf in browser using express js

How to send a pdf file from Node/Express app to the browser

Send pdf via express to js client and download

虽然这些问题与此非常相关,但我认为我的问题是由于对回调或请求/响应缺乏了解。我想正确地学习这一点 - 不仅仅是寻求答案 - 但事实上,我的时间变得非常紧迫,并且很快需要一个解决方案。

【问题讨论】:

    标签: javascript node.js google-api google-drive-api google-api-nodejs-client


    【解决方案1】:

    您应该能够简单地将返回的可读流通过管道传输到 express res 对象(这是一个可写流):

    app.get('/download_pdf', (req, res) => {
        drive.files.get({
            fileId: "your-file-id-here",
            alt: 'media'
        })
        .on('end', function () {
            console.log('Done');
        })
        .on('error', function (err) {
            console.log('Error during download', err);
        })
        .pipe(res);    
    });
    

    编辑:

    here 所述,drive.files.get 确实返回了一个承诺。所以你需要把它改成:

    app.get('/download_pdf', (req, res) => {
        drive.files.get({
            fileId,
            alt: 'media'
        }, {
            responseType: 'stream'
        }).then(response => {
            response.data
            .on('end', function () {
                console.log('Done');
            })
            .on('error', function (err) {
                console.log('Error during download', err);
            })
            .pipe(res);
        });
    });
    

    【讨论】:

    • 您好,感谢您的回复。我尝试了这个并遇到了documentID的问题。如果我直接将 ID 作为字符串提供,则会收到语法错误:Unexpected token ','
    • 例如drive.files.get({'xfg3H32randomStringKdCt4X', alt: 'media'}, {responseType: etc etc....}
    • 按照你之前的方式通过sourceID,我编辑了答案。
    • 谢谢,我已将其替换为 fileId,但现在我得到:'TypeError: driveStream.pipe is not a function' 感谢您的帮助,我将继续调查
    • 所以我通过对您提供的代码进行轻微更改来解决它。我试图编辑您的答案以添加此内容,但编辑队列显然已满。如果您在某个时候更改它,我会将您的答案标记为解决方案。再次感谢!
    【解决方案2】:

    所以我想出了一个办法。我不确定这是否是不好的做法,但它似乎有效。我通过将一个作为响应和一个作为 res 来区分这两个响应对象。

    app.get('/download_pdf', (req, res) => {
        const docId = req.query.id;
        drive.files.get({
            fileId: docId,
            alt: 'media'
        }, {
            responseType: 'stream'
        }).then(response => {
            response.data
            .on('end', function () {
                console.log('Done');
            })
            .on('error', function (err) {
                console.log('Error during download', err);
            })
            .pipe(res);
        });
    
    });
    

    在其他人有类似问题的情况下发布。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-02
      • 1970-01-01
      • 2011-08-15
      • 2013-04-11
      • 2021-12-07
      相关资源
      最近更新 更多