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

Node.js如何从POST请求上传Base64图片并按分类存储到MongoDB

核心结论

你当前的请求是JSON格式带Base64编码图片,multer本身仅用于处理multipart/form-data类型的文件上传请求,无法直接识别JSON中的Base64字段,因此不需要在controller中调用multer,直接自己实现Base64转存逻辑是最适配你现有代码的方案。


方案1:保留现有JSON请求结构(推荐,改动量最小)

无需修改前端现有请求逻辑,仅在后端autoUpload控制器中新增Base64转存文件的处理逻辑即可:

步骤1:新增工具函数处理Base64转存

const fs = require('fs/promises');
const path = require('path');

// 预设存储目录,可根据自己的项目路径调整
const NAMED_SHROOM_DIR = path.join(__dirname, '../uploads/shrooms/named');
const NAMELESS_SHROOM_DIR = path.join(__dirname, '../uploads/shrooms/nameless');

// 自动创建不存在的目录
const ensureDirExists = async (dirPath) => {
  try {
    await fs.access(dirPath);
  } catch {
    await fs.mkdir(dirPath, { recursive: true });
  }
};

/**
 * 转存Base64图片到指定目录
 * @param {string} base64Str 前端传的Base64图片字符串
 * @param {string} shroomName 蘑菇名称,用于判断存储目录
 * @param {string} imgKey 图片标识,区分img1/img2
 * @param {number} timestamp 时间戳,避免文件名重复
 * @returns {string} 图片存储路径,可直接存入MongoDB
 */
const saveBase64Img = async (base64Str, shroomName, imgKey, timestamp) => {
  // 按名称区分存储目录
  const saveDir = shroomName === 'Unknown' 
    ? NAMELESS_SHROOM_DIR 
    : path.join(NAMED_SHROOM_DIR, shroomName.replace(/\s+/g, '_'));
  await ensureDirExists(saveDir);
  
  // 去除Base64前缀,转成Buffer写入文件
  const base64Data = base64Str.replace(/^data:image\/\w+;base64,/, '');
  const buffer = Buffer.from(base64Data, 'base64');
  const fileName = `${timestamp}_${imgKey}.jpg`;
  const fullPath = path.join(saveDir, fileName);
  
  await fs.writeFile(fullPath, buffer);
  // 返回相对路径或者静态资源可访问路径,根据自己的需求调整
  return fullPath.replace(path.join(__dirname, '../public'), '');
};

步骤2:在autoUpload控制器中处理请求

exports.autoUpload = async (req, res) => {
  try {
    const { tourID } = req.params;
    const { email, name, shrooms } = req.body;
    
    // 遍历处理每个蘑菇项的两张图片
    const processedShrooms = await Promise.all(shrooms.map(async (shroom, index) => {
      const { name: shroomName, time, gps, img1, img2 } = shroom;
      // 加上index避免同一时间上传的多张图片重名
      const baseTime = Date.now() + index * 10;
      const img1Path = await saveBase64Img(img1, shroomName, 'img1', baseTime);
      const img2Path = await saveBase64Img(img2, shroomName, 'img2', baseTime + 1);
      return {
        shroomName,
        time,
        gps,
        img1Path,
        img2Path
      };
    }));
    
    // 替换成你自己的MongoDB存储逻辑
    const saveResult = await TourModel.create({
      tourID,
      email,
      userName: name,
      shrooms: processedShrooms
    });
    
    res.status(200).json({ code: 0, data: saveResult });
  } catch (err) {
    console.error('上传处理失败:', err);
    res.status(500).json({ code: 1, msg: '上传失败' });
  }
};

注意事项

默认express的JSON中间件请求体大小限制为100kb,传大体积Base64图片会报错,需要调整配置:

app.use(express.json({ limit: '50mb' })); // 大小可根据自己的业务需求调整

方案2:改用multer处理(适合单张图片大于10M的场景)

如果你的图片体积较大,Base64会带来33%左右的体积膨胀,这时可以修改前端请求格式为multipart/form-data,用multer原生处理文件流,内存占用更低:

配置动态路径的multer中间件

const multer = require('multer');

const storage = multer.diskStorage({
  destination: async function (req, file, cb) {
    // 前端需要在formData中同步传入对应图片的shroomName字段
    const shroomName = req.body[`${file.fieldname}_name`];
    const saveDir = shroomName === 'Unknown' 
      ? NAMELESS_SHROOM_DIR 
      : path.join(NAMED_SHROOM_DIR, shroomName.replace(/\s+/g, '_'));
    await ensureDirExists(saveDir);
    cb(null, saveDir);
  },
  filename: function (req, file, cb) {
    cb(null, `${Date.now()}_${file.originalname}`);
  }
})

const autoUploadMulter = multer({ storage: storage });
// 修改路由配置,any()支持接收任意数量的文件
router.post('/autoUpload/:tourID', autoUploadMulter.any(), ctrlTour.autoUpload);

前端需要把每个图片文件、对应的蘑菇名称字段、其他业务参数都放到formData中提交,后端在req.files中拿到所有上传的文件,和其他参数拼接后存入MongoDB即可。


内容的提问来源于stack exchange,提问作者ProblemUMad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 05:27:02