【问题标题】:How can I temporarily store a pdf in Firebase filesystem?如何在 Firebase 文件系统中临时存储 pdf?
【发布时间】:2021-07-05 12:06:33
【问题描述】:

我在 NodeJS 的服务器端使用 JSPDF 创建一个 pdf。完成后,我想在 Google Drive 中为用户创建一个新文件夹,将 pdf 上传到该文件夹​​,并将其发送到客户端(浏览器)供用户查看。

我遇到了两个问题。首先,如果我通过 pdf.output() 在响应中发送 pdf,则图像无法正确显示。它们是扭曲的,就好像每一行像素都偏移了一些量。竖线“|”而是呈现为对角线“\”。下面是一个例子。


之前


之后

我的解决方法是使用 doc.save() 将其保存到文件系统,然后使用 fs.readFileSync(filepath) 将其发送到浏览器。 但是,我发现在远程运行时,我没有文件权限来保存和阅读 pdf。经过一些研究和修补,我认为我无法更改这些权限。这是我得到的错误:

错误:EROFS:只读文件系统,打开“./temp/output.pdf”
在 Object.openSync (fs.js:443:3)
在 Object.writeFileSync (fs.js:1194:35)
在 Object.v.save (/workspace/node_modules/jspdf/dist/jspdf.node.min.js:86:50626)
等等……

所以我有这个 JSPDF 对象,我相信我需要更改权限以允许写入/读取或获取 jspdf 对象,或者,我猜,将其格式更改为 Google 驱动器接受的格式,例如流还是缓冲区对象?

下面的链接让我认为这些权限无法更改,因为它指出:“这些文件在只读目录中可用”。
https://cloud.google.com/functions/docs/concepts/exec#file_system
我也不知道服务器文件系统在“哪里”,或者如何访问它。因此,我认为最好的做法是查看以不同格式发送 pdf。 我检查了 jsPDF 文档以了解 pdf.output() 可以返回的类型。这些包括字符串、数组缓冲区、窗口、blob、jsPDF。
https://rawgit.com/MrRio/jsPDF/master/docs/jsPDF.html#output

我的简化代码如下:

const express = require('express');
const fs = require('fs');
const app = express();
const { jsPDF } = require('jspdf');

const credentials = require(credentialsFilepath);
const scopes = [scopes in here];
const auth = new google.auth.JWT(
    credentials.client_email, null,
    credentials.private_key, scopes
);
const drive = google.drive({version: 'v3', auth});
//=========================================================================
app.post('/submit', (req, res) => {
  var pdf = new jsPDF();

  // Set font, fontsize. Added some text, etc.
  pdf.text('blah blah', 10, 10);

  // Add image (signature) from canvas, which is passed as a dataURL
  pdf.addImage(img, 'JPEG', 10, 10, 50, 20);

  pdf.save('./temp/output.pdf');

  drive.files.create({
    resource: folderMetaData,
    fields: 'id'
  })
  .then(response => {
    // Store pdf in newly created folder
    var fileMetaData = {
      'name': 'filename.pdf',
      'parents': [response.data.id],
    };
    var media = {
      mimeType: 'application/pdf',
      body: fs.createReadStream('./temp/output.pdf'),
    };
    drive.files.create({
      resource: fileMetaData,
      media: media,
      fields: 'id'
    }, function(err, file) {
      if(err){
        console.error('Error:', err);
      }else{
        // I have considered piping 'file' back in the response here but can't figure out how
        console.log('File uploaded');
      }
   });
  })
  .catch(error => {
    console.error('Error:', error);
  });

  // Finally, I attempt to send the pdf to client/browser
  res.setHeader('Content-Type', 'application/pdf');
  res.send(fs.readFileSync('./temp/output.pdf'));
})

编辑:经过更多搜索,我发现了一个类似的问题,它解释了 fs 模块用于读取/写入本地文件存储。
EROFS error when executing a File Write function in Firebase

【问题讨论】:

  • 当您说图像无法正确显示时-这发生在客户端或您保存pdf文件的位置或双方?而您的问题仅询问有关向客户端发送 pdf 的问题?在客户端,您要保存它还是在浏览器中打开它?另外,你用什么做前端?
  • 您好,感谢您的回复。据我观察,它发生在客户端(我不知道如何在服务器端查看 pdf)。我只是想在浏览器中打开它来查看,但可以选择下载。对于前端,我相信我们只是在使用 HTML/CSS 和 JS
  • 这个文件暂时保存在./temp/filename你应该去检查一下。
  • ./temp/filename 是本地文件路径。如果我在本地运行服务器,是的,我可以在该文件中查看它。我已经检查过了,它看起来不错。它工作得很好。这不是我遇到的问题。如果我部署项目并远程运行它,我将不再有权读取/写入此目录。大概是因为我不再访问本地目录,而是访问由 Firebase 托管的远程目录。
  • 为此,您应该授予写入权限,只要我知道您可以在 Firebase 控制台中创建权限。我不确定this 的事情是否会有所帮助,但检查它是一个不错的选择。

标签: node.js google-drive-api jspdf


【解决方案1】:

经过进一步阅读,我最终找到了解决方案。我不确定这对谁有用,但是...

原来 Firebase 文件系统只有 1 个允许您写入的目录(其余的都是只读的)。该目录名为 tmp,我使用 tmp 节点模块 [安装:npm i tmp] 访问它,因为尝试使用 pdf.save('./tmp/output.pdf') 手动引用路径不起作用。

所以对我的代码的唯一更改是添加以下行:
var tmp = require('tmp');
var tmpPath = tmp.tmpNameSync();

然后将 './temp/output.pdf' 的所有实例替换为 tmpPath

【讨论】:

    猜你喜欢
    • 2015-06-29
    • 2013-02-02
    • 2019-03-06
    • 2010-09-16
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    相关资源
    最近更新 更多