如何将包含Blob的复杂对象通过fetch发送到Node.js服务端
现有实现的问题根因如下:
- 直接把普通JS对象
data传入FormData.append()方法时,浏览器会自动调用对象的toString()方法,最终只会传输[object Object]字符串,无法保留原有结构,更不会正确序列化其中的Blob字段。 - Node.js原生和常用的
express.json()中间件都不支持解析multipart/form-data类型的请求体,没有配置对应解析中间件的情况下req.body自然为undefined。
客户端改造
你需要先把data对象中的非Blob类型字段序列化为JSON,Blob类型字段单独追加到FormData中,示例代码如下:
const fd = new FormData(); // 分离Blob和普通字段 const blobFields = {}; const commonFields = {}; for (const key in data) { if (data[key] instanceof Blob) { // 第三个参数可指定Blob对应的文件名,非文件类Blob可省略或自定义命名 fd.append(key, data[key], data[key].name || `blob_${key}`); blobFields[key] = true; } else { commonFields[key] = data[key]; } } // 普通字段和Blob字段映射关系转为JSON后追加到FormData fd.append('common_data', JSON.stringify(commonFields)); fd.append('blob_field_map', JSON.stringify(blobFields)); fetch('/mother/new-card', { method: 'POST', body: fd, })
服务端改造
首先安装multer中间件,用于解析multipart/form-data类型的请求:
npm install multer
如果使用Koa框架,可安装@koa/multer适配,用法基本一致。
控制器层代码调整
const multer = require('multer'); // 配置内存存储,无需将Blob落地到磁盘即可读取内容 const storage = multer.memoryStorage(); const upload = multer({ storage: storage }); // 配置解析FormData的中间件,any()可接收所有文件字段,也可通过fields()指定接收的字段提高安全性 router.post('/new-card', upload.any(), newCard); function newCard(req, res) { motherService.newCard(req) .then(result => res.json(result)) .catch(err => { console.log(err); res.json(err) }); }
服务层代码调整
async function newCard(req) { // 解析普通字段和Blob字段映射 const commonData = JSON.parse(req.body.common_data); const blobFieldMap = JSON.parse(req.body.blob_field_map); // 合并Blob内容到普通对象中 req.files.forEach(file => { if (blobFieldMap[file.fieldname]) { // file.buffer为Blob对应的二进制内容,需要还原为Blob的话可直接new Blob([file.buffer]) commonData[file.fieldname] = file.buffer; } }); console.log('完整接收的data对象:', commonData); return { success: true, data: commonData } }
内容的提问来源于stack exchange,提问作者Sara Ree
相关产品推荐
相关产品推荐

