React中保存Firebase返回的.docx文件报错问题排查
解决Firebase函数返回Word文档Buffer后客户端无法打开的问题
核心问题:Node.js 的 res.json() 会将 Buffer 序列化为 JSON 对象(格式为 { type: 'Buffer', data: [字节数组] }),而非原始二进制数据。客户端直接使用该对象创建 Blob,实际保存的是 JSON 字符串,而非合法的 docx 二进制内容,导致文件损坏。
方案一:服务端直接返回二进制响应(推荐)
修改 Firebase 函数,直接返回 Buffer 并设置正确的 HTTP 头,避免 JSON 序列化的问题:
exports.test = functions.https.onRequest((req, res) => { cors(req, res, async () => { const parameters = req.body.data; const analyzer = new Analyzer(parameters); analyzer.analyze(); const docxwritter = new DocxWritter(analyzer); const buffer = await docxwritter.save(); // 设置Word文档的MIME类型 res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'); // 设置下载文件名 res.setHeader('Content-Disposition', 'attachment; filename="word-document.docx"'); // 直接发送二进制Buffer res.send(buffer); }); });
客户端改用普通 fetch 请求(不再使用 Callable 函数):
// 替换为你的Firebase函数URL const functionUrl = 'https://<your-project-id>.cloudfunctions.net/test'; fetch(functionUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ data: parameters }), }) .then(response => response.blob()) .then(blob => { const downloadUrl = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = downloadUrl; link.download = 'word-document.docx'; document.body.appendChild(link); link.click(); // 清理资源 URL.revokeObjectURL(downloadUrl); document.body.removeChild(link); }) .catch(error => console.error('下载失败:', error));
方案二:客户端处理序列化后的Buffer对象
如果坚持使用 Firebase Callable 函数,需要将客户端接收到的序列化 Buffer 对象转换为 Uint8Array,再创建 Blob:
const functions = getFunctions(); const callableFunction = httpsCallable(functions, 'test'); callableFunction(parameters).then((res) => { // 提取序列化后的Buffer数据数组,转换为Uint8Array const serializedBuffer = res.data.data; const uint8Array = new Uint8Array(serializedBuffer.data); // 创建Blob时指定正确的MIME类型 const wordBlob = new Blob([uint8Array], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }); const downloadUrl = URL.createObjectURL(wordBlob); const link = document.createElement('a'); link.href = downloadUrl; link.download = 'word-document.docx'; document.body.appendChild(link); link.click(); // 清理资源 URL.revokeObjectURL(downloadUrl); document.body.removeChild(link); }).catch((err) => { console.log(err); });
验证说明
你本地测试生成的文件正常,说明模板渲染和 Buffer 生成逻辑没问题,问题完全出在传输过程中的数据格式处理。以上两种方案都能确保客户端获取到正确的二进制 docx 内容,解决文件无法打开的问题。
内容的提问来源于stack exchange,提问作者roee
相关产品推荐
相关产品推荐

