0

I'd like to create an Excel File stream in Node Express and send the Excel file in the Node Express response to then be downloaded by the client browser. Problem is I'm completely inexperienced with streams and I'm not even sure this is possible.

A little background: I'm using a node package ExcelJs (https://www.npmjs.com/package/exceljs) to create an Excel document. I can create the Excel file just fine. I know that Express provides res.download option to download files to the client browser, but I think res.download requires an actual file with a path in order to download to the client browser. This code will be hosted on AWS, and I want to avoid having to create and save a file in S3 before grabbing the file and downloading it to the client browser.

ExcelJS has an option to create a; file, stream, or buffer excel. Is it be possible to create a stream with the required data and then send that file stream in the response to be downloaded in the client browser?

Joe Schmoe
  • 31
  • 3
  • 6

2 Answers2

0

//Create a middleware and a readable stream

const excelStream = //generate your excel stream here

//Filestream middleware
const streamW = () => {
return (req, res, next) => {

//Pipe the excel stream to the response
excelStream.pipe(res)
 next()
  }
}


router.get('/excelstream', streamW()/* consume the middleware*/, (req, res) => {
 //Send the data to the front end
 res
});

Algo7
  • 2,122
  • 1
  • 8
  • 19
0

My favourite (awesome) solution:

res.xlsx('awesome-template.xlsx', awesomeViewModel, 'report.xlsx');

My favourite solution is to expand response object by function xlsx which generate the file using a template with view model and write it into res (download into browser)

import {Renderer} from 'xls-renderer'

const renderer = new Renderer();

router.use((req, res, next) => { // register middleware

  res.xlsx = (template, vm, fileName) => { // add function into res object
    const workbook = renderer.renderFromFile(template, vm);

    res.set({
      'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      'Content-Disposition': `attachment; filename="${filenName}"`,
    });

    await (await workbook).xlsx.write(res);
  };


  next();
});

Alternate solutions:

I. ExcelJS workbook.xlsx.write(res) way:

import {Workbook} from 'exceljs'

// creation code
const wb = new Workbook();
// ... const wsA = wb.addWorksheet("WsA");

// response headers
res.set({
  'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  'Content-Disposition': `attachment; filename="from-exceljs.xlsx"`,
});

// write into response
wb.xlsx.write(res);

II. pure XlsxRender way:

npm install --save xlsx-renderer
const workbook = renderer.renderFromFile('template.xlsx', viewModel);

res.set({
    'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    'Content-Disposition': `attachment; filename="from-xlsx-renderer.xlsx"`,
});

await (await workbook).xlsx.write(res); // yeah, it returns ExcelJs Workbook, so same as above.