写入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
相关产品推荐
相关产品推荐

