Firebase 存储 + nodejs 中的 docxtemplater
Firebase Storage + docxtemplater in nodejs
我无法在节点 js 中加载 firebase 存储文档(最好是二进制文件)以便我可以在其上生成 docxtemplater 文档。我对 docxtemplater 很陌生,真的很想将它用于我的 webapp
这是可以做到的吗?
下面是我得到的代码,但我认为它没有正确地从我的 firebase 存储中加载文档:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const {Storage} = require('@google-cloud/storage');
var PizZip = require('pizzip');
var Docxtemplater = require('docxtemplater');
admin.initializeApp();
const BUCKET = 'gs://mpcwapp.appspot.com';
const https = require('https');
const storage = new Storage({
projectId: 'myapp' });
const cors = require('cors')({origin: true});
exports.test2 = functions.https.onCall((data, context) => {
// The error object contains additional information when logged with JSON.stringify (it contains a properties object containing all suberrors).
function replaceErrors(key, value) {
if (value instanceof Error) {
return Object.getOwnPropertyNames(value).reduce(function(error, key) {
error[key] = value[key];
return error;
}, {});
}
return value;
}
function errorHandler(error) {
console.log(JSON.stringify({error: error}, replaceErrors));
if (error.properties && error.properties.errors instanceof Array) {
const errorMessages = error.properties.errors.map(function (error) {
return error.properties.explanation;
}).join("\n");
console.log('errorMessages', errorMessages);
// errorMessages is a humanly readable message looking like this :
// 'The tag beginning with "foobar" is unopened'
}
throw error;
}
//Load the docx file as a binary
let file_name = 'input.docx';
const myFile =storage.bucket(BUCKET).file(file_name);
var content = myFile.createReadStream();
var zip = new PizZip(content);
var doc;
try {
doc = new Docxtemplater(zip);
} catch(error) {
// Catch compilation errors (errors caused by the compilation of the template : misplaced tags)
errorHandler(error);
}
//set the templateVariables
doc.setData({
first_name: 'John',
last_name: 'Doe',
phone: '0652455478',
description: 'New Website'
});
try {
// render the document (replace all occurences of {first_name} by John, {last_name} by Doe, ...)
doc.render();
}
catch (error) {
// Catch rendering errors (errors relating to the rendering of the template : angularParser throws an error)
errorHandler(error);
}
var buf = doc.getZip()
.generate({type: 'nodebuffer'});
buf.pipe(myFile.createWriteStream());
});
任何帮助将不胜感激我真的被困住了。
首先,如果您要在 Firebase Functions 中部署代码逻辑,请确保它在您的 list of exports 中。
我尝试重现您代码的行为并注意到错误的根本原因是您代码中的这一部分:
var content = myFile.createReadStream();
var zip = new PizZip(content);
根据此 pizzip 似乎接受 Buffer 输入 documentation. However, createReadStream()
returns ReadableStream 因此存在不匹配在所需参数之间。
我能想到的解决方案有两种:
- 首先,下载并存储文件(在
/tmp
中)。然后使用 fs.readFileSync()
. 读取文件
- 跳过将文件保存到文件系统,获取文件对象的缓冲区。
对于第二个选项,您需要了解流的工作原理。这 可以给你一个良好的开端。例如,您可以像这样从 ReadableStream 获取缓冲区:
const remoteFile = storage.bucket("bucket-name").file("file-name")
const readable = remoteFile.createReadStream()
var buffers = [];
readable.on('data', (buffer) => {
buffers.push(buffer)
});
readable.on('end', () => {
var buffer = Buffer.concat(buffers);
var zip = new PizZip(buffer);
var doc;
try {
doc = new Docxtemplater(zip);
} catch(error) {
errorHandler(error);
}
// ... rest of your code
});
我无法在节点 js 中加载 firebase 存储文档(最好是二进制文件)以便我可以在其上生成 docxtemplater 文档。我对 docxtemplater 很陌生,真的很想将它用于我的 webapp
这是可以做到的吗?
下面是我得到的代码,但我认为它没有正确地从我的 firebase 存储中加载文档:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const {Storage} = require('@google-cloud/storage');
var PizZip = require('pizzip');
var Docxtemplater = require('docxtemplater');
admin.initializeApp();
const BUCKET = 'gs://mpcwapp.appspot.com';
const https = require('https');
const storage = new Storage({
projectId: 'myapp' });
const cors = require('cors')({origin: true});
exports.test2 = functions.https.onCall((data, context) => {
// The error object contains additional information when logged with JSON.stringify (it contains a properties object containing all suberrors).
function replaceErrors(key, value) {
if (value instanceof Error) {
return Object.getOwnPropertyNames(value).reduce(function(error, key) {
error[key] = value[key];
return error;
}, {});
}
return value;
}
function errorHandler(error) {
console.log(JSON.stringify({error: error}, replaceErrors));
if (error.properties && error.properties.errors instanceof Array) {
const errorMessages = error.properties.errors.map(function (error) {
return error.properties.explanation;
}).join("\n");
console.log('errorMessages', errorMessages);
// errorMessages is a humanly readable message looking like this :
// 'The tag beginning with "foobar" is unopened'
}
throw error;
}
//Load the docx file as a binary
let file_name = 'input.docx';
const myFile =storage.bucket(BUCKET).file(file_name);
var content = myFile.createReadStream();
var zip = new PizZip(content);
var doc;
try {
doc = new Docxtemplater(zip);
} catch(error) {
// Catch compilation errors (errors caused by the compilation of the template : misplaced tags)
errorHandler(error);
}
//set the templateVariables
doc.setData({
first_name: 'John',
last_name: 'Doe',
phone: '0652455478',
description: 'New Website'
});
try {
// render the document (replace all occurences of {first_name} by John, {last_name} by Doe, ...)
doc.render();
}
catch (error) {
// Catch rendering errors (errors relating to the rendering of the template : angularParser throws an error)
errorHandler(error);
}
var buf = doc.getZip()
.generate({type: 'nodebuffer'});
buf.pipe(myFile.createWriteStream());
});
任何帮助将不胜感激我真的被困住了。
首先,如果您要在 Firebase Functions 中部署代码逻辑,请确保它在您的 list of exports 中。
我尝试重现您代码的行为并注意到错误的根本原因是您代码中的这一部分:
var content = myFile.createReadStream();
var zip = new PizZip(content);
根据此 pizzip 似乎接受 Buffer 输入 documentation. However, createReadStream()
returns ReadableStream 因此存在不匹配在所需参数之间。
我能想到的解决方案有两种:
- 首先,下载并存储文件(在
/tmp
中)。然后使用fs.readFileSync()
. 读取文件
- 跳过将文件保存到文件系统,获取文件对象的缓冲区。
对于第二个选项,您需要了解流的工作原理。这
const remoteFile = storage.bucket("bucket-name").file("file-name")
const readable = remoteFile.createReadStream()
var buffers = [];
readable.on('data', (buffer) => {
buffers.push(buffer)
});
readable.on('end', () => {
var buffer = Buffer.concat(buffers);
var zip = new PizZip(buffer);
var doc;
try {
doc = new Docxtemplater(zip);
} catch(error) {
errorHandler(error);
}
// ... rest of your code
});