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

写入XLSX模板的函数返回undefined,如何正确返回文件流作为接口响应

问题根源

你当前的问题由两处异步使用错误导致:

  • objectsToTemplateWorkBook 函数虽然声明返回 Promise 类型,但实际使用回调式的 fs.readFile 接口,函数执行时回调还未触发,dataBlob 尚未赋值就被返回,因此始终为 undefined
  • 请求处理函数中调用异步的 objectsToTemplateWorkBook 时未加 await,无法拿到异步执行的结果

修复方案

1. 重写 objectsToTemplateWorkBook 函数,改为标准 async 异步实现

使用 fs.promises 接口替代回调式写法,让函数真正返回可等待的 Promise:

import fs from 'fs/promises'
import path from 'path'

export const objectsToTemplateWorkBook = async (): Promise<any> => {
  const XlsxTemplate = require('xlsx-template')
  // 等待文件读取完成
  const data = await fs.readFile(path.join(__dirname, 'test_template.xlsx'))
  console.log(__dirname)
  // 创建模板
  const template = new XlsxTemplate(data)
  const sheetNumber = 1
  const values = {
    people: [
      { name: 'John Smith', age: 20 },
      { name: 'Bob Johnson', age: 22 },
    ],
  }
  // 替换占位符
  template.substitute(sheetNumber, values)
  // 返回生成的二进制数据
  return template.generate()
}

2. 修改请求处理函数,增加 await 调用异步方法

async handle(request: Request, response: Response) {
  try {
    const fileName = 'test.xlsx'
    // 增加await等待异步方法执行完成拿到结果
    const binary = await objectsToTemplateWorkBook()
    response.setHeader(
      'Content-Disposition',
      'attachment; filename=' + encodeURIComponent(fileName)
    )
    // 使用标准的xlsx Content-Type,兼容性更好
    response.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
    response.end(binary, 'binary')
  } catch (error) {
    console.log(error)
    response.status(500).send('文件生成失败')
  }
}

补充说明

  • 上述代码中对文件名做了encodeURIComponent编码,可兼容中文文件名场景
  • 错误处理中增加了状态码设置,避免前端把错误响应当成文件处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 13:15:04