多Blob图片上传单文件正常、多文件报错问题排查求助
多图片Blob上传失败,单文件正常的排查与解决
我正在开发网站的多图片上传功能,采用Blob格式将文件上传至服务器。单文件上传可正常运行,但上传2个及以上文件时会出现错误——服务端检查req相关属性均返回undefined,仅多文件上传会触发该问题。
前端状态定义
type BlobNull = { 0: Blob | null 1: Blob | null 2: Blob | null 3: Blob | null } const [blobs, setBlobs] = React.useState < BlobNull > ({ 0: null, 1: null, 2: null, 3: null, }) const [catalog, setCatalog] = React.useState({ ProductName: "", cShopVisiblity: true, Delivery: true, ItemPrice: "", Quantitiy: "", Notes: "Notes" })
前端提交处理函数
const handleAdd = async () => { startLoading(); try { if (Object.values(catalog).every(val => val.toString().trim() !== "")) { const formData = new FormData(); Object.keys(catalog).forEach(key => formData.append(key, catalog[key])); Object.values(blobs).filter(val => val !== null).forEach((blob, id) => formData.append(`Img`, blob)) const { data, isOK } = await catalogService.add(formData); if (isOK) { addToastMsg(`Details saved : ${data.ProductName} ${data.Quantitiy}`, "success"); setCatalog({ ProductName: "", cShopVisiblity: true, Delivery: true, ItemPrice: "", Quantitiy: "", Notes: "Notes" }); setOpen(false); } else { throw new Error("Internal server error"); } } else { addToastMsg("Please fill all the fields required.", "warning"); } } catch (e) { console.error("error saving form", e); addToastMsg( "Unable to save details, please re validate entered values", "error" ); } endLoading(); }
后端接口代码
exports.add = async (req, res) => { try { // if (req.file) console.log("file"); // if (req.files) console.log("files"); // if (req.Img) console.log("Img"); // if (req.data) console.log("data"); if (req.files?.length > 1 && Array.isArray(req.files['Img'])) { multiUpload(req, res, async function (err) { if (err) { return res.status(400).json({ message: 'Error uploading files' }); } const files = req.files; const imageBuffers = files.map((file, id) => ({ [`Img${id > 0 ? id : ''}`]: Buffer.from(file.buffer) })) const catalog = await catalogsModel.create({ ...req.body, ...imageBuffers }); res.status(201).json({ success: true, data: catalog, }); }); } else { singleUpload(req, res, async function (err) { if (err) { // handle the error here return res.status(400).json({ message: 'Error uploading file' }); } if (req.file) { const imageBuffer = Buffer.from(req.file.buffer); const catalog = await catalogsModel.create({ ...req.body, Img: imageBuffer }); res.status(201).json({ success: true, data: catalog, }); } else { const catalog = await catalogsModel.create(req.body); res.status(201).json({ success: true, data: catalog, }); } }); } } catch (error) { console.log("API error", error); if (!res.headersSent) { res.send(500).json({ success: false, error: "Server error", }); } return; } };
问题核心原因
后端逻辑执行顺序错误:你先判断
req.files?.length > 1 && Array.isArray(req.files['Img']),但此时multiUpload文件上传中间件还未执行,req.files尚未被赋值,必然是undefined。这会导致代码直接进入singleUpload分支,但singleUpload仅支持单文件处理,多文件传入后无法正确解析,最终req.file和req.files全为undefined。中间件拆分冗余:分开使用
singleUpload和multiUpload不仅增加复杂度,还会导致多文件场景下中间件不匹配,无法正确解析请求。
修复方案
1. 调整后端逻辑顺序,统一中间件
移除先判断文件数量的逻辑,先执行支持多文件的上传中间件,再处理业务数据。以multer为例:
// 假设已配置multer存储 const upload = multer({ storage: ... }); // 接口直接使用支持多文件的中间件,限制最多4个文件 exports.add = upload.array('Img', 4), async (req, res) => { try { // 中间件执行后,req.files为上传的文件数组,req.body为表单数据 let imageBuffers = {}; if (req.files?.length) { req.files.forEach((file, id) => { imageBuffers[`Img${id > 0 ? id : ''}`] = Buffer.from(file.buffer); }); } const catalog = await catalogsModel.create({ ...req.body, ...imageBuffers }); res.status(201).json({ success: true, data: catalog }); } catch (error) { console.log("API error", error); if (!res.headersSent) { res.status(500).json({ success: false, error: "Server error" }); } } };
2. 前端补充文件名(可选)
给FormData中的Blob添加文件名,避免部分中间件解析异常:
Object.values(blobs).filter(val => val !== null).forEach((blob, id) => { // 自定义文件名,后缀可根据实际文件类型调整 formData.append(`Img`, blob, `product-image-${id}.png`); })
内容的提问来源于stack exchange,提问作者toygr
相关产品推荐
相关产品推荐

