【发布时间】: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