使用Formidable上传多文件至AWS S3时出现路径未定义错误
多文件上传至AWS S3时Formidable报错:"path"参数未定义
我用Formidable实现文件上传到AWS S3,单文件上传正常,但多文件上传时Postman报错:The "path" argument must be of type string or an instance of Buffer or URL. Received undefined。打印文件对象类型是Object,但怀疑element.filepath无法访问,相关代码如下:
exports.addProduct = asyncHandler(async (req, res) => { const form = formidable({ multiples: true, keepExtensions: true, }); form.parse(req, async function (err, fields, files) { try { if (err) { throw new CustomError(err.message || "Something went wrong", 500); } let productId = new Mongoose.Types.ObjectId().toHexString(); // check for fields if ( !fields.name || !fields.price || !fields.description || !fields.collectionId ) { throw new CustomError("Please fill all details", 500); } // handling images let imgArrayResp = Promise.all( Object.keys(files).map(async (filekey, index) => { const element = files[filekey]; console.log(`line 50 ${element.filepath} `) console.log(typeof(element)) const data = fs.readFileSync(element.filepath); console.log("line 62", data); // console.log(typeof(s3FileUpload)) const upload = await s3FileUpload({ bucketName: config.S3_BUCKET_NAME, key: `products/${productId}/photo_${index + 1}.png`, body: data, contentType: element.mimetype, }); return { secure_url: upload.Location, }; }) ); let imgArray = await imgArrayResp; const product = await Product.create({ _id: productId, photos: imgArray, ...fields, }); if (!product) { throw new CustomError("Product was not created", 400); //remove image } res.status(200).json({ success: true, product, }); } catch (error) { return res.status(500).json({ success: false, message: error.message || "Something went wrong", }); } }); });
问题根源
当Formidable开启multiples: true时,若通过同名字段上传多个文件,该字段对应的files[filekey]会是一个文件对象数组,而非单个文件对象。你的代码直接用Object.keys(files).map遍历,当遇到数组时,element就是整个数组,自然没有filepath属性,导致fs.readFileSync接收到undefined参数报错。
修复代码
方案一:用flat()统一展开数组
直接将files的值展开为一维数组,统一处理每个文件对象:
// 处理图片的修正代码 let imgArrayResp = Promise.all( Object.values(files).flat().map(async (element, index) => { console.log(`文件路径: ${element.filepath}`); console.log(typeof element); // 可选:添加路径有效性检查 if (!element.filepath) { throw new CustomError(`第${index+1}个文件路径无效`, 400); } const data = fs.readFileSync(element.filepath); const upload = await s3FileUpload({ bucketName: config.S3_BUCKET_NAME, key: `products/${productId}/photo_${index + 1}.png`, body: data, contentType: element.mimetype, }); return { secure_url: upload.Location, }; }) );
方案二:手动判断数组类型
更严谨地判断每个文件项是否为数组,分别处理:
// 处理图片的修正代码 let imgArrayResp = Promise.all( Object.keys(files).flatMap((filekey) => { const fileItems = files[filekey]; // 将单个文件转为数组,统一遍历逻辑 const fileList = Array.isArray(fileItems) ? fileItems : [fileItems]; return fileList.map(async (element, index) => { if (!element.filepath) { throw new CustomError(`第${index+1}个文件路径无效`, 400); } const data = fs.readFileSync(element.filepath); const upload = await s3FileUpload({ bucketName: config.S3_BUCKET_NAME, key: `products/${productId}/photo_${index + 1}.png`, body: data, contentType: element.mimetype, }); return { secure_url: upload.Location, }; }); }) );
额外排查建议
- 先打印
console.log(files),确认多文件上传时的结构,明确哪些字段是数组 - 确保Postman中多文件上传时使用同名字段(比如都用
photos作为字段名),或者根据实际字段名调整遍历逻辑
内容的提问来源于stack exchange,提问作者Aaro Oral
相关产品推荐
相关产品推荐

