es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

extrayendo el contenido antes de subirlo

Estoy utilizando multer s3 para subir a Digital Ocean Space. Estoy enviando un archivo zip que quiero descomprimir antes de subirlo a Space. ¿Cómo puedo descomprimir el archivo antes de subirlo a multer?

Editar: El archivo zip tiene múltiples carpetas y múltiples archivos en él.

He creado hasta la parte donde puedo subir un archivo zip

const spacesEndpoint = new AWS.Endpoint('sgp1.digitaloceanspaces.com');
const s3 = new AWS.S3({
  endpoint: spacesEndpoint,
  accessKeyId: process.env.SPACES_ACCESS_ID,
  secretAccessKey: process.env.SPACES_ACCESS_KEY,
});

const upload = multer({
  storage: multerS3({
    s3,
    bucket: "mi-bucket",
    acl: 'public-read',
    key: function (req, file, cb) {
      cb(null, file.originalname);
    },
  }),
});

router.post(
  '/upload',
  upload.fields([{ name: 'name' }, { name: 'data' }]),
  async function (req, res, next) {
      res.send('status ok');
  },
);
Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para descomprimir el archivo antes de subirlo a Multer, puedes usar el paquete unzipper. Primero, necesitas instalarlo usando npm install unzipper. Luego, puedes modificar la función upload para incluir un middleware que descomprima el archivo antes de subirlo. Aquí tienes un ejemplo de código:

    const unzipper = require('unzipper');
    
    const upload = multer({
      storage: multerS3({
        s3,
        bucket: "my-bucket",
        acl: 'public-read',
        key: function (req, file, cb) {
          cb(null, file.originalname);
        },
      }),
      fileFilter: function (req, file, cb) {
        if (file.mimetype !== 'application/zip') {
          return cb(new Error('Solo se permiten archivos ZIP'));
        }
        cb(null, true);
      },
      // agregar middleware para descomprimir el archivo antes de subirlo
      // asumiendo que el archivo se llama "data"
      // y los archivos descomprimidos se almacenarán en un directorio llamado "unzipped"
      // en la misma carpeta que el archivo zip subido
      // este middleware también manejará el caso en el que el archivo zip tenga múltiples carpetas anidadas
      // y múltiples archivos en él
      // mediante la descompresión de cada archivo y carpeta de forma recursiva
      // haciendo referencia a esta respuesta de stack overflow: https://stackoverflow.com/a/59772895/7942063
      async function (req, res, next) {
        const data = req.files.data[0].buffer;
        const unzipStream = unzipper.Parse();
        const files = [];
        unzipStream.on('entry', async (entry) => {
          const fileName = entry.path;
          if (entry.type === 'Directory') {
            files.push({ name: fileName, type: 'directorio' });
            entry.autodrain();
          } else {
            const filePromise = new Promise((resolve, reject) => {
              const chunks = [];
              entry.on('data', (chunk) => {
                chunks.push(chunk);
              }).on('end', async () => {
                const fileBuffer = Buffer.concat(chunks);
                const filePath = `unzipped/${fileName}`;
                await s3.putObject({
                  Bucket: 'my-bucket',
                  Key: filePath,
                  Body: fileBuffer,
                  ACL: 'public-read',
                  ContentType: mime.getType(filePath),
                }).promise();
                files.push({ name: fileName, type: 'archivo' });
                resolve();
              }).on('error', (err) => {
                reject(err);
              });
            });
            await filePromise;
          }
        }).on('finish', async () => {
          // todos los archivos se han descomprimido y subido a S3
          // puedes almacenar la lista de archivos subidos en una base de datos o devolverla como respuesta
          res.locals.files = files;
          next();
        }).on('error', (err) => {
          next(err);
        });
        unzipStream.write(data);
        unzipStream.end();
      },
    });
    

    Este código utiliza el método unzipper.Parse() para crear un flujo que lee el búfer del archivo ZIP y extrae cada archivo y carpeta dentro de él. Para cada archivo, crea una promesa que sube el archivo descomprimido a S3 utilizando el método s3.putObject(). Se espera a que se resuelva la promesa para asegurarse de que todos los archivos se hayan subido antes de continuar. La lista de archivos subidos se almacena en el objeto res.locals.files y se puede utilizar según sea necesario. Ten en cuenta que se utiliza el método upload.fields() para esperar que se envíen tanto los campos name como data en la solicitud.

Comments are closed.