javascriptnode.jsexcelxlsxsheetjs

Download excel file created in node using SheetJS/XLXS [NodeJS] [React]


I'm trying to generate a xlsx file using SheetJS in node. Then in my frontend I have a button to call this route and download the file. Currently I have the following:

// backend code
export function exportExcel(req: Request, res: Response) {
  try {
    const workbook = utils.book_new();
    const fileName = "sample";
    const dataSheet = utils.json_to_sheet(sampleData);
    utils.book_append_sheet(workbook, dataSheet, fileName.replace("/", ""));
    const binaryWorkbook = write(workbook, {
      type: "array",
      bookType: "xlsx",
    });

    return res.status(OK).send(binaryWorkbook);
  } catch (_error) {
    return res.sendStatus(500)
  }
}

Then in the front end I have the following:

const handleExcelExport = () => {
 const { data } = await axios.get(
    `/export-excel`,
    {
      responseType: "blob",
    }
  ).then(response => {
     const blob = new Blob([response], {
       type: "application/octet-stream",
     });
     const link = document.createElement("a");
     link.href = window.URL.createObjectURL(blob);
     link.download = fileName;
     link.click();
  }
}

// I simply call the above in the onClick handler in a button
<button onClick={handleExcelExport}> Export excel </button>

I can see that a download file appears when I click on the button but I can't open it. MS Excel says that ""File format or file extension is not valid..."


Solution

  • I fixed by changing to the following in the BE:

      const binaryWorkbook = write(workbook, {
          type: "buffer",
          bookType: "xlsx",
        });
    

    and also adding headers per the docs:

    res.setHeader(
          "Content-Disposition",
          'attachment; filename="SheetJSNode.xlsx"'
        );
       
    res.setHeader("Content-Type", "application/vnd.ms-excel");
    

    Then in the frontend I changed the response type and content-type to

    {
       responseType: "arraybuffer",
    }
    

    Blob content-type

    const blob = new Blob([response], {
              type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
            });