Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

346
Vistas
Cómo hacer que el cliente descargue un archivo muy grande que se genera sobre la marcha

Tengo una función de exportación que lee toda la base de datos y crea un archivo .xls con todos los registros. A continuación, el archivo se envía al cliente.

Por supuesto, el momento de exportar la base de datos completa requiere mucho tiempo y la solicitud terminará pronto en un error de tiempo de espera.

¿Cuál es la mejor solución para manejar este caso?

Escuché algo sobre hacer una cola con Redis, por ejemplo, pero esto requerirá dos solicitudes: una para iniciar el trabajo que generará el archivo y la segunda para descargar el archivo generado.

¿Es esto posible con una sola solicitud del cliente?

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

Exportación de Excel:

Utilice flujos . Lo que sigue es una idea aproximada de lo que podría hacerse:

  1. Utilice el módulo exceljs . Porque tiene una API de transmisión dirigida a este problema exacto.

     var Excel = require('exceljs')
  2. Ya que estamos tratando de iniciar una descarga. Escriba encabezados apropiados para la respuesta.

     res.status(200); res.setHeader('Content-disposition', 'attachment; filename=db_dump.xls'); res.setHeader('Content-type', 'application/vnd.ms-excel');
  3. Cree un libro de trabajo respaldado por Streaming Excel Writer . El flujo dado al escritor es la respuesta del servidor.

     var options = { stream: res, // write to server response useStyles: false, useSharedStrings: false }; var workbook = new Excel.stream.xlsx.WorkbookWriter(options);
  4. Ahora, el flujo de transmisión de salida está configurado. para la transmisión de entrada, prefiera un controlador de base de datos que brinde resultados de consulta/cursor como una transmisión.

  5. Defina una función asíncrona que vuelque 1 tabla en 1 hoja de trabajo.

     var tableToSheet = function (name, done) { var str = dbDriver.query('SELECT * FROM ' + name).stream(); var sheet = workbook.addWorksheet(name); str.on('data', function (d) { sheet.addRow(d).commit(); // format object if required }); str.on('end', function () { sheet.commit(); done(); }); str.on('error', function (err) { done(err); }); }
  6. Ahora, exportemos algunas tablas de db, usando mapSeries del módulo asíncrono:

     async.mapSeries(['cars','planes','trucks'],tableToSheet,function(err){ if(err){ // log error } res.end(); })

Exportación CSV:

Para la exportación a CSV de un solo módulo de tabla/colección, se puede usar fast-csv :

 // response headers as usual res.status(200); res.setHeader('Content-disposition', 'attachment; filename=mytable_dump.csv'); res.setHeader('Content-type', 'text/csv'); // create csv stream var csv = require('fast-csv'); var csvStr = csv.createWriteStream({headers: true}); // open database stream var dbStr = dbDriver.query('SELECT * from mytable').stream(); // connect the streams dbStr.pipe(csvStr).pipe(res);

Ahora está transmitiendo datos de la base de datos a la respuesta HTTP, convirtiéndolos al formato xls/csv sobre la marcha. No es necesario almacenar en búfer o almacenar todos los datos en la memoria o en un archivo.

over 4 years ago · Santiago Trujillo Denunciar

0

No es necesario que envíe el archivo completo una vez, puede enviar este archivo por fragmentos (línea por línea, por ejemplo), simplemente use res.write(chunk) y res.end() al finalizar para marcarlo como completado.

over 4 years ago · Santiago Trujillo Denunciar

0

Puede enviar la información del archivo como una secuencia, enviando cada fragmento individual a medida que se crea a través res.write(chunk) o, si enviar el archivo fragmento por fragmento no es una opción y tiene que esperar el archivo completo antes de enviar cualquier información, siempre puede mantener abierta la conexión configurando la duración del tiempo de espera en Infinito o cualquier valor que crea que será lo suficientemente alto para permitir que se cree el archivo. Luego configure una función que cree el archivo .xls y:

1) Acepta una devolución de llamada que recibe la salida de datos como un argumento una vez que está lista, envía esos datos y luego cierra la conexión, o;

2) Devuelve una promesa que se resuelve con la salida de datos una vez que está lista, lo que le permite enviar el valor resuelto y cerrar la conexión al igual que con la versión de devolución de llamada.

Se vería algo como esto:

 function xlsRouteHandler(req, res){ res.setTimeout(Infinity) || res.socket.setTimeout(Infinity) //callback version createXLSFile(...fileCreationArguments, function(finishedFile){ res.end(finishedFile) }) //promise version createXLSFile(...fileCreationArguments) .then(finishedFile => res.end(finishedFile)) }

Si aún le preocupa el tiempo de espera, siempre puede configurar un temporizador de intervalo para enviar un mensaje res.write() ocasional para evitar un tiempo de espera en la conexión del servidor y luego cancelar ese intervalo una vez que el contenido final del archivo esté listo para ser enviado .

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda