2 votes

L'API GridFS de MongoDB renvoie un .zip corrompu

Le contexte :

Application Node.js / Loopback dont la base de données est alimentée par un fichier .zip contenant des données provenant d'applications CRM d'entreprise existantes. J'essaie de stocker un binaire du fichier .zip dans ma base de données à des fins de débogage de production en utilisant GridFS car le fichier peut être >16mb et le récupérer à tout moment en utilisant un point de terminaison d'administration.

Problème :

Je peux stocker le fichier zip avec la fonction storeLatestZipFile dans mon module et je peux le récupérer en utilisant un point de terminaison que la fonction createLatestZipEndpoint crée.

Cependant, le fichier .zip que je reçois est plus volumineux que le fichier original (14,7 mb contre 21,1 mb) et il est également corrompu.

Je suppose que je ne code pas mes données ou que je n'utilise pas correctement l'API GridFS. Quelqu'un aurait-il repéré les erreurs dans mon code / aurait-il plus d'expérience dans le stockage des .zips avec GridFS ?

Le module en question :

const { pino } = require('amf-logger');
const fs = require('fs');
const mongo = require('mongodb');

const log = pino({ name: 'bot-zip-upload-storage' });

/**
 * @param {string} path Path to the zip file to be persisted.
 * @param {object} app Loopback application instance.
 */
function storeLatestZipFile(path = './', app = {}) {
  log.info('**** Starting streaming current uploaded zip to DB ****');
  const zipReadStream = fs.createReadStream(path, { encoding: 'binary' });
  const { db } = app.dataSources.mongo.connector;
  const bucket = new mongo.GridFSBucket(db);
  bucket.delete('zipfile', () => {
    log.info('deleted old zipfile');

    const uploadStream = bucket.openUploadStreamWithId(
      'zipfile',
      `bot-data-${new Date().toISOString()}`,
      {
        contentType: 'application/zip'
      }
    );

    zipReadStream.pipe(uploadStream);
  });
}

/**
 * @param {object} app Loopback application instance.
 */
async function createLatestZipEndpoint(app = {}) {
  if (!app.get) {
    log.error("app object does not have 'get' property.");
    return;
  }

  app.get('/api/admin/latestzip', async (req, res) => {
    if (!req.headers.latestfile || req.headers.latestfile !== process.env.ADMIN_LATESTFILE) {
      res.sendStatus(403);
      return;
    }

    try {
      const { db } = app.dataSources.mongo.connector;
      const bucket = new mongo.GridFSBucket(db);
      res.writeHead(200, { 'Content-Type': 'application/zip' });
      const downloadStream = bucket.openDownloadStream('zipfile');
      log.info('download stream opened, begin streaming');
      downloadStream.pipe(res);
    } catch (err) {
      log.error(`error getting zipfile: ${err}`);
      res.sendStatus(500);
    }
  });
}

module.exports = {
  storeLatestZipFile,
  createLatestZipEndpoint
};

2voto

Juha Lindstedt Points 26

Avez-vous essayé createReadStream sans buffer -encodage ?

const zipReadStream = fs.createReadStream(path);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X