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
相关产品推荐
相关产品推荐

