如何在 NodeJS MongoDB 中保存和检索 pdf 文件
How to Save and Retrieve a pdf file in MongoDB in NodeJS
我有一个问题,我将在 Node.js 服务器后端使用 Express 创建的一个小 pdf 文件 (~128KB) 保存到 Mongodb 中的文档中。我没有使用 Mongo GridFS,因为文件将始终低于 16MB 的限制。该集合具有以下架构:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ReportsSchema = new Schema({
ReportFileData: Buffer,
Cert_objid: { type: Schema.Types.ObjectId, ref: 'Certs' },
Report_Type: String,
Note: String,
Dau_objID: { type: Schema.Types.ObjectId, ref: 'Dau' },
Pau_objID: { type: Schema.Types.ObjectId, ref: 'Pau' }
});
module.exports = Reports = mongoose.model('Reports', ReportsSchema);
我使用以下代码创建 pdf 文件并保存。我没有包含 docDefinition,因为如果它直接保存到服务器,它会生成正确的文件。
const PdfPrinter = require('pdfmake/src/printer');
const path = require('path');
const moment = require('moment');
const Reports = require('../../models/Reports'); // Mongoose Schema
const createFAReport = data => {
docDefinition...
createPdfBinary(docDefinition, binary => {
const rpt = new Reports({
ReportFileData: binary,
Cert_objid: data._id,
Report_Type: 'Water Use Report',
Note: 'Testing 123'
});
rpt.save(err => {
if (err) throw err;
});
});
const createPdfBinary = (pdfDoc, callback) => {
const fonts = {
Roboto: {
normal: path.join(__dirname, '../../', '/fonts/Roboto-Regular.ttf'),
bold: path.join(__dirname, '../../', '/fonts/Roboto-Medium.ttf'),
italics: path.join(__dirname, '../../', '/fonts/Roboto-Italic.ttf'),
bolditalics: path.join(__dirname, '../../', '/fonts/Roboto-MediumItalic.ttf')
}
};
const printer = new PdfPrinter(fonts);
const doc = printer.createPdfKitDocument(pdfDoc);
const chunks = [];
let result;
doc.on('data', function(chunk) {
chunks.push(chunk);
});
doc.on('end', function() {
result = Buffer.concat(chunks);
callback('data:application/pdf;base64,' + result.toString('base64'));
});
doc.end();
};
然后从 MongoDB 检索编码文档并将其写入本地文件进行测试我使用了以下代码(请注意聚合是为了获取检索正确报告所需的一些关联字段):
router.get('/getReport', passport.authenticate('jwt', { session: false }), (req, res) => {
Certs.aggregate([
{
$match: {
Cert_ID: '1578'
}
},
{
$lookup: {
from: 'reports',
localField: '_id',
foreignField: 'Cert_objid',
as: 'rpt'
}
},
{
$unwind: {
path: '$rpt',
includeArrayIndex: '<<string>>',
preserveNullAndEmptyArrays: false
}
}
]).then(result => {
result.map(rslt => {
console.log(rslt.Cert_ID);
res.json({ msg: 'Got the report.' });
const fullfilePath = path.join(__dirname, '../../', '/public/pdffiles/', `1578.pdf`
);
fs.writeFile(fullfilePath, rslt.rpt.ReportFileData, 'base64', () => {
console.log('File Saved.');
});
});
});
});
一切似乎都正常,除了当我打开文件时出现文件损坏的错误。我想知道将它保存到 "base64" 是否有问题,或者 MongoDB 的数据类型是否有问题。数据类型是缓冲区,所以你会把它作为缓冲区检索吗?任何帮助将不胜感激。
我不建议将 pdf 或图像直接写入数据库。以下是有关 Storing Images in DB - Yea or Nay?
原因的一些信息
您通常保存文件名并将文件存储在文件系统上,您自己的或更具可扩展性的选项将类似于 S3。
这是一个可能对您有所帮助的模块https://www.npmjs.com/package/formidable,如果您打算推出自己的模块,您仍然可以从中获得一些灵感。
我有一个问题,我将在 Node.js 服务器后端使用 Express 创建的一个小 pdf 文件 (~128KB) 保存到 Mongodb 中的文档中。我没有使用 Mongo GridFS,因为文件将始终低于 16MB 的限制。该集合具有以下架构:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ReportsSchema = new Schema({
ReportFileData: Buffer,
Cert_objid: { type: Schema.Types.ObjectId, ref: 'Certs' },
Report_Type: String,
Note: String,
Dau_objID: { type: Schema.Types.ObjectId, ref: 'Dau' },
Pau_objID: { type: Schema.Types.ObjectId, ref: 'Pau' }
});
module.exports = Reports = mongoose.model('Reports', ReportsSchema);
我使用以下代码创建 pdf 文件并保存。我没有包含 docDefinition,因为如果它直接保存到服务器,它会生成正确的文件。
const PdfPrinter = require('pdfmake/src/printer');
const path = require('path');
const moment = require('moment');
const Reports = require('../../models/Reports'); // Mongoose Schema
const createFAReport = data => {
docDefinition...
createPdfBinary(docDefinition, binary => {
const rpt = new Reports({
ReportFileData: binary,
Cert_objid: data._id,
Report_Type: 'Water Use Report',
Note: 'Testing 123'
});
rpt.save(err => {
if (err) throw err;
});
});
const createPdfBinary = (pdfDoc, callback) => {
const fonts = {
Roboto: {
normal: path.join(__dirname, '../../', '/fonts/Roboto-Regular.ttf'),
bold: path.join(__dirname, '../../', '/fonts/Roboto-Medium.ttf'),
italics: path.join(__dirname, '../../', '/fonts/Roboto-Italic.ttf'),
bolditalics: path.join(__dirname, '../../', '/fonts/Roboto-MediumItalic.ttf')
}
};
const printer = new PdfPrinter(fonts);
const doc = printer.createPdfKitDocument(pdfDoc);
const chunks = [];
let result;
doc.on('data', function(chunk) {
chunks.push(chunk);
});
doc.on('end', function() {
result = Buffer.concat(chunks);
callback('data:application/pdf;base64,' + result.toString('base64'));
});
doc.end();
};
然后从 MongoDB 检索编码文档并将其写入本地文件进行测试我使用了以下代码(请注意聚合是为了获取检索正确报告所需的一些关联字段):
router.get('/getReport', passport.authenticate('jwt', { session: false }), (req, res) => {
Certs.aggregate([
{
$match: {
Cert_ID: '1578'
}
},
{
$lookup: {
from: 'reports',
localField: '_id',
foreignField: 'Cert_objid',
as: 'rpt'
}
},
{
$unwind: {
path: '$rpt',
includeArrayIndex: '<<string>>',
preserveNullAndEmptyArrays: false
}
}
]).then(result => {
result.map(rslt => {
console.log(rslt.Cert_ID);
res.json({ msg: 'Got the report.' });
const fullfilePath = path.join(__dirname, '../../', '/public/pdffiles/', `1578.pdf`
);
fs.writeFile(fullfilePath, rslt.rpt.ReportFileData, 'base64', () => {
console.log('File Saved.');
});
});
});
});
一切似乎都正常,除了当我打开文件时出现文件损坏的错误。我想知道将它保存到 "base64" 是否有问题,或者 MongoDB 的数据类型是否有问题。数据类型是缓冲区,所以你会把它作为缓冲区检索吗?任何帮助将不胜感激。
我不建议将 pdf 或图像直接写入数据库。以下是有关 Storing Images in DB - Yea or Nay?
原因的一些信息您通常保存文件名并将文件存储在文件系统上,您自己的或更具可扩展性的选项将类似于 S3。
这是一个可能对您有所帮助的模块https://www.npmjs.com/package/formidable,如果您打算推出自己的模块,您仍然可以从中获得一些灵感。