Как сохранить и получить PDF-файл в MongoDB в NodeJS - PullRequest
0 голосов
/ 04 января 2019

У меня проблема с сохранением небольшого файла PDF (~ 128 КБ), созданного в моей серверной части сервера Node.js с использованием Express, для документа в Mongodb.Я не использовал Mongo GridFS, потому что размер файлов не превышает 16 МБ.Коллекция имеет следующую схему:

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 проблема.Тип данных является буфером, поэтому вы бы взяли его как буфер?Любая помощь будет оценена.

1 Ответ

0 голосов
/ 08 января 2019

Я бы не рекомендовал записывать PDF-файлы или изображения непосредственно в базу данных.Вот некоторая информация о том, почему Хранение изображений в БД - да или нет?

Обычно вы сохраняете имя файла и сохраняете файл в файловой системе, либо ваш собственный, либо более масштабируемый вариант будетчто-то вроде S3.

Вот модуль, который может вам помочь https://www.npmjs.com/package/formidable, и если вы планируете развернуть свой собственный, вы все равно можете получить от него вдохновение.

...