React/Node.js中基于Buffer数组实现文件创建、展示与下载
你拿到的{type: "Buffer", data: [字节数组]}是Node.js Buffer执行JSON序列化后的标准结构,data字段存储的是文件二进制内容的字节码,不管是React前端直接处理,还是Node.js服务端做流转发,核心都是先把这个字节数组还原为可操作的二进制对象,再实现预览、下载逻辑。
React 前端侧实现(无需服务端中转)
核心依赖:浏览器原生Blob API + URL对象
第一步:将Buffer JSON结构转为Blob对象
首先把字节数组转为Uint8Array,再结合文件对应的MIME类型生成Blob实例。示例数据开头字节为137,80,78,71,是PNG图片的标准文件头,对应MIME为image/png,其他常见格式对应MIME:PDF为application/pdf、docx为application/vnd.openxmlformats-officedocument.wordprocessingml.document、xlsx为application/vnd.openxmlformats-officedocument.spreadsheetml.sheet。/** * 把Buffer JSON转成浏览器可识别的Blob * @param {Object} bufferJson 接口返回的Buffer结构数据 * @param {string} mimeType 文件MIME类型 * @returns {Blob} */ const convertBufferToBlob = (bufferJson, mimeType) => { const uint8Arr = new Uint8Array(bufferJson.data); return new Blob([uint8Arr], { type: mimeType }); };第二步:实现文件预览
用URL.createObjectURL()基于Blob生成本地临时访问地址,直接绑定到对应预览组件即可:图片类直接给<img>标签的src属性,PDF可以嵌入<iframe>,复杂格式可以搭配对应生态组件(比如react-pdf预览PDF、mammoth预览docx)。import { useState, useEffect } from 'react'; function AttachmentPreview({ bufferData, mimeType }) { const [previewSrc, setPreviewSrc] = useState(''); useEffect(() => { const blob = convertBufferToBlob(bufferData, mimeType); const objectUrl = URL.createObjectURL(blob); setPreviewSrc(objectUrl); // 组件卸载时释放临时地址,避免内存泄漏 return () => URL.revokeObjectURL(objectUrl); }, [bufferData, mimeType]); // 以PNG图片预览为例,其他格式替换对应渲染标签即可 return <img src={previewSrc} alt="附件预览" style={{ maxWidth: '100%' }} />; }第三步:实现文件下载
同样基于Blob生成临时地址,动态创建a标签触发浏览器下载行为,下载完成后释放临时内存:/** * 触发文件下载 * @param {Object} bufferJson Buffer结构数据 * @param {string} mimeType 文件MIME * @param {string} fileName 下载保存的文件名 */ const triggerDownload = (bufferJson, mimeType, fileName) => { const blob = convertBufferToBlob(bufferJson, mimeType); const objectUrl = URL.createObjectURL(blob); const aTag = document.createElement('a'); aTag.href = objectUrl; aTag.download = fileName; document.body.appendChild(aTag); aTag.click(); document.body.removeChild(aTag); URL.revokeObjectURL(objectUrl); }; // 调用示例:<button onClick={() => triggerDownload(bufferData, 'image/png', '测试图片.png')}>下载附件</button>
Node.js 服务端实现(流转发模式)
如果需要在服务层统一处理文件返回,直接把Buffer JSON还原为原生Buffer对象后,通过响应流返回给前端即可:
- 第一步:还原Node原生Buffer实例,直接调用
Buffer.from()传入字节数组即可,无需额外依赖// bufferJson为拿到的{type:"Buffer", data:[...]}结构 const fileBuffer = Buffer.from(bufferJson.data); - 第二步:配置响应头返回文件流,以Express框架为例:
const express = require('express'); const app = express(); app.get('/api/file/download', (req, res) => { // 实际场景从数据库/其他服务拿到Buffer JSON结构 const bufferJson = { type: "Buffer", data: [137,80,78,71,13,10,26] }; const fileBuffer = Buffer.from(bufferJson.data); const mimeType = 'image/png'; const fileName = '测试图片.png'; // 设置响应类型 res.setHeader('Content-Type', mimeType); // 配置为下载模式:Content-Disposition设为attachment;需要浏览器直接预览则设为inline res.setHeader( 'Content-Disposition', `attachment; filename*=UTF-8''${encodeURIComponent(fileName)}` ); // 直接返回Buffer内容 res.send(fileBuffer); }); app.listen(3000);
注意事项
- 前端生成的Object URL必须在不需要时调用
URL.revokeObjectURL()释放,大文件场景下如果不释放会造成明显的内存占用问题- MIME类型必须和文件实际格式匹配,否则会出现预览失败、下载后文件无法打开的问题,可以通过文件头魔数自动识别格式,避免硬编码错误
- 中文文件名在服务端响应时必须做UTF-8编码处理,否则会出现文件名乱码
内容的提问来源于stack exchange,提问作者Mahesh Jagdale

