Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

349
Views
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 answers
Answer question

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 Report

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!