You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Excel.js导出用户列表至Xlsx遇障,求专家指导及简便方案

问题分析与解决方案

核心矛盾点拆解

你的代码存在几个关键问题,直接导致导出失败:

  1. 格式完全冲突:后端用Excel.js生成Excel工作簿,却强行转成CSV格式输出,前端又要保存为xlsx文件,格式不匹配自然无法打开。
  2. 二进制数据损坏:后端把Excel的二进制buffer转成字符串发送,破坏了文件的二进制结构,前端拿到的是无效数据。
  3. 前端接收方式错误:用response.text()接收二进制文件,会导致编码混乱,无法还原成有效Excel文件。

修正后的后端代码(直接输出Excel二进制)

export const getUserExcel = async (req, res) => {
  try {
    const users = await User.find({});

    const workbook = new exceljs.Workbook();
    const sheet = workbook.addWorksheet("users");

    const header = [
      { header: "用户名", key: "userName", width: 20 },
      { header: "名字", key: "firstName", width: 20 },
      { header: "姓氏", key: "lastName", width: 20 },
      { header: "邮箱", key: "email", width: 20 },
      { header: "角色", key: "role", width: 20 },
    ];

    sheet.columns = header;
    users.forEach((user) => sheet.addRow(user.toObject()));
    sheet.getRow(1).eachCell((cell) => { cell.font = { bold: true }; });

    // 设置正确的Excel响应头
    res.setHeader(
      "Content-Type",
      "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
    );
    res.setHeader(
      "Content-Disposition",
      "attachment; filename=users.xlsx"
    );

    // 直接发送二进制buffer,不做字符串转换
    const buffer = await workbook.xlsx.writeBuffer();
    res.send(buffer);
  } catch (error) {
    console.error("导出用户失败:", error);
    res.status(500).send({ message: "服务器内部错误" });
  }
};

修正后的前端代码

const handleExport = async () => {
  try {
    const response = await fetch("/api/user/get-user-excel");
    if (!response.ok) throw new Error("请求失败");
    
    const blob = await response.blob();
    fileSaver.saveAs(blob, "users.xlsx");
  } catch (error) {
    console.error("下载Excel失败:", error);
  }
};

更简便的替代方案(SheetJS/xlsx库)

如果觉得Excel.js操作繁琐,可以用SheetJS的xlsx库,前后端都能快速实现导出:

后端实现

import XLSX from 'xlsx';

export const getUserExcel = async (req, res) => {
  try {
    const users = await User.find({}).lean(); // 直接获取普通对象,无需toObject()转换
    // 把JSON转成工作表
    const worksheet = XLSX.utils.json_to_sheet(users, {
      header: ["userName", "firstName", "lastName", "email", "role"],
      skipHeader: false
    });
    // 替换表头为中文
    XLSX.utils.sheet_add_aoa(worksheet, [["用户名", "名字", "姓氏", "邮箱", "角色"]], { origin: "A1" });
    
    const workbook = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(workbook, worksheet, "users");
    
    // 生成Excel二进制buffer
    const buffer = XLSX.write(workbook, { type: "buffer", bookType: "xlsx" });
    
    res.setHeader(
      "Content-Type",
      "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
    );
    res.setHeader(
      "Content-Disposition",
      "attachment; filename=users.xlsx"
    );
    res.send(buffer);
  } catch (error) {
    console.error("导出用户失败:", error);
    res.status(500).send({ message: "服务器内部错误" });
  }
};

前端实现

和之前修正后的前端代码完全一致,无需改动。

内容的提问来源于stack exchange,提问作者Fraz Khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 08:34:56