You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 10:10:31