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

MERN栈中使用Multer处理图片上传及Postman测试咨询

MERN栈产品图片上传:Express端Multer优化及Postman测试方法

一、现有代码问题修正

1. fileUpload.js 问题修正

原代码存在三个问题:缺失path模块导致文件名处理报错、相对存储路径易出问题、文件过滤拒绝时无错误提示。修正后代码如下:

const multer = require('multer')
const { v4: uuidv4 } = require('uuid')
const path = require('path')
const fs = require('fs')

// 自动创建uploads目录,避免上传失败
const uploadsDir = path.join(__dirname, '../uploads')
if (!fs.existsSync(uploadsDir)) {
  fs.mkdirSync(uploadsDir, { recursive: true })
}

const storage = multer.diskStorage({
    destination: function(req, file, cb) {
        cb(null, uploadsDir) // 使用绝对路径避免跨目录问题
    },
    filename: function(req, file, cb){
        cb(null, uuidv4() + '-' + Date.now() + path.extname(file.originalname) )
    }
})

const fileFilter = (req, file, cb) => {
    const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png']
    if(allowedTypes.includes(file.mimetype)) {
        cb(null, true)
    } else {
        cb(new Error('仅支持JPEG、JPG、PNG格式的图片'), false)
    }
}

const upload = multer({storage, fileFilter})

module.exports = upload

2. Product控制器 createProduct 方法修正

原代码把整个req.file对象存入数据库,但模型中image是String类型,需改为存储文件的相对路径:

const Product = require('../models/Product')
const { StatusCodes } = require('http-status-codes')
const { BadRequestError, NotFoundError } = require('../errors') 
const path = require('path')

const createProduct = async (req, res) => {
    // 若有上传文件,存入相对路径方便前端访问
    if (req.file) {
        const relativePath = path.join('/uploads', req.file.filename)
        req.body.image = relativePath
    }
    req.body.createdBy = req.user.userId
    const product = await Product.create(req.body)
    res.status(StatusCodes.CREATED).json({ product })
}

// 其余方法保持不变
const getAllProducts = async (req, res) => {
    res.send('get All products')
}

const getProduct = async (req, res) => {
    res.send('get product')
}

const updateProduct = async (req, res) => {
    res.send('update product')
}

const deleteProduct = async (req, res) => {
    res.send('delete product')
}

module.exports = {
    getAllProducts, createProduct, getProduct, updateProduct, deleteProduct
}

3. 其他代码确认

  • Product模型:image字段为String类型,符合修正后存储路径的要求,无需修改
  • Product路由:upload.single('image')配置正确,对应上传字段名image,无需修改

二、Postman测试API步骤

  1. 启动Express服务器,确保数据库连接正常
  2. 打开Postman,创建POST请求,URL填写你的产品接口地址(比如http://localhost:5000/api/products)
  3. 在Headers中添加用户认证信息(比如JWT Token,因为接口需要req.user.userId)
  4. 切换到Body标签,选择form-data格式:
    • 添加产品文本字段:
      • 键:name,值:产品名称(如"无线耳机"),类型选Text
      • 键:category,值:产品分类(如"数码产品"),类型选Text
      • 键:quantity,值:产品数量(如100),类型选Text
      • 键:price,值:产品价格(如199),类型选Text
      • 键:description,值:产品描述,类型选Text
    • 添加图片字段:
      • 键:image,类型选择File,点击Select Files选择本地的JPG/PNG图片
  5. 点击Send发送请求:
    • 成功时会返回创建的产品数据,image字段显示存储的相对路径
    • 失败时根据错误信息排查(比如文件格式不对、必填字段缺失)

三、前端React适配提示

前端提交表单时需用FormData包装数据和文件:

const handleSubmit = async (e) => {
  e.preventDefault()
  const formData = new FormData()
  formData.append('name', name)
  formData.append('category', category)
  formData.append('quantity', quantity)
  formData.append('price', price)
  formData.append('description', description)
  formData.append('image', imageFile) // imageFile是input[type="file"]获取的文件对象

  const response = await fetch('/api/products', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}` // 携带认证Token
    },
    body: formData
  })
  const data = await response.json()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 19:25:26