首页 > 解决方案 > 如何使用 Multer 在 MERN Stack 应用程序中上传图像文件

问题描述

我正在尝试在我的项目中使用 multer 将图像作为文件上传,但我不知道为什么我在 req.files 上看到的控制台后端的 onCreate 请求:[]; (空数组)。

这是我创建元素的地方:

    const [imagesColors, setImagesColors] = useState([{image: [], color: ''}])
    
    const createProduct = (e) => {
        e.preventDefault ();
    
        const data = new FormData()
    
    data.append("name", name)
        data.append("description", description)
        data.append("processor", processor)
        data.append("ram", ram)
        data.append("storage", storage)
        data.append("imagesColors", imagesColors)
        data.append("price", price)
        data.append("type", type)
    
        console.log(data)
    
        fetch ('http://localhost:5000/products/create', {
          method: 'POST',
          body: data
        })...
    
    const handleInputChangeColor = (e, index) => {
        const { name, value } = e.target;
        const list = [...imagesColors];
        list[index][name] = value;
        setImagesColors(list);
      };
    
      const handleInputChangeImage = (e, index) => {
        const name = e.target.name;
        const file = e.target.files;
        const list = [...imagesColors];
        list[index][name] = file;
        setImagesColors(list);
      };
    
return (
...
    {imagesColors.map((x, i) => {
                        return (
                          <div className="box">
                            <label htmlFor="file" className="file--Input--Container">
                              <input
                                type="file"
                                id="file"
                                multiple
                                name="image"
                                className="file--Input"
                                filename="imageFile"
                                placeholder="Product Image"
                                onChange={e => handleInputChangeImage(e, i)}
                              />
                              <div className="file--Label--Container">
                                 <FaCloudUploadAlt className="upload--Icon"/> Upload Images
                              </div>
                            </label>
                            <select
                              onChange={e => handleInputChangeColor(e, i)}
                              value={x.color}
                              name="color"
                              defaultValue=""
                            >
                              <option selected value="">Color</option>
                              <option value='#4f5b66'>Space-gray</option>
                              <option value='#a7adba'>Silver</option>
                              <option value='#FFFFFF'>White</option>
                              <option value='#F63204'>Red</option>
                              <option value='#000000'>Black</option>
                              <option value='#0095CB'>Pacific-Blue</option>
                            </select>
                            <div className="btn-box">
                              {imagesColors.length !== 1 && <button onClick={() => handleRemoveClick(i)}>Remove</button>}
                              {imagesColors.length - 1 === i && <button onClick={handleAddClick}>Add</button>}
                            </div>
                          </div>
                        );
                      })}

当我 console.logimagesColors它返回的状态时:

在此处输入图像描述

这是后端带有 multer 函数的 create 函数:

const imageStorage = multer.diskStorage({
    destination: (req, file, callback) => {
        callback(null, "../../shpJS/frontend/src/styles/images")
    },
    filename: (req, file, callback) => {
        callback(null, file.name)
    }
})

const uploads = multer({storage: imageStorage})

router.post('/create', uploads.array("imagesColors"), async (req, res) => {
    console.log(req, ' asd')
    try {
        const data = {
            name: req.body.name,
            description: req.body.description,
            processor: req.body.processor,
            ram: req.body.ram,
            storage: req.body.storage,
            imagesColors: req.files,
            price: req.body.price,
            type: req.body.type,
            likes: req.body.likes
        }
        let product = await productService.create(data)
        res.status(201).json(product)
    } catch (error) {
        res.status(500).json({error: error})
    }
})

来自请求的控制台结果:

在此处输入图像描述

标签: reactjsmongodbexpressmultermern

解决方案


要使用 FormData API 在前端发送多个文件,您必须逐个附加这些文件。您可以将它们附加到同一个字段,该字段将作为数组到达后端。如果您想随每个文件发送其他数据,请以相同的顺序将该数据附加到不同的字段。

在您的情况下,它看起来像这样:

for (const imageAndColor of imagesColors) {
  data.append('images', imageAndColor.image);
  data.append('colors', imageAndColor.color);
}

并在后端更改uploads.array("imagesColors")uploads.array("images"). 您的图像将在 中req.files,颜色将在req.body.colors. 保证两个数组的顺序——第一个图像是两个数组中的第一个元素,第二个图像是第二个元素,依此类推。


推荐阅读