Перехваты React и загрузка изображений Axios с помощью Multer

#node.js #reactjs #react-hooks

#node.js #reactjs #реагирующие хуки

Вопрос:

Я пытаюсь добавить возможность загружать изображение, а затем обновлять пользовательский объект с помощью этого пути к изображению. Когда я загружаю изображение с помощью Insomnia client и отправляю запрос, я могу успешно добавить изображение и путь к MongoDB. Маршрут пользователя NodeJS ниже:

 const express = require ("express"); 
const router = express.Router(); 
const bcrypt = require("bcryptjs"); 
const jwt = require("jsonwebtoken"); 
const Users = require("../models/users"); 
const auth = require("../middleware/auth"); 
const multer = require('multer');

const storage = multer.diskStorage({
    destination: function(req, file, cb) {
        cb(null, './uploads/'); 
    }, 
    filename: function(req, file, cb){
        cb(null, file.originalname); 
    }
}); 

const fileFilter = (req, file, cb) => {
    // reject a file
    if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png' || file.mimetype == "image/jpg") {
      cb(null, true);
        } else {
            cb(null, false);
            return cb(new Error('Only .png, .jpg and .jpeg format allowed!'));
        }
  };

const upload = multer({storage: storage, limits: {
    fileSize: 1024 * 1024 * 5 
    }, 

    fileFilter: fileFilter
});
// REQUEST TO FIND USER BY ID AND ADD A PROFILE PICTURE 
router.put('/update/:id', upload.single('userImage'), (req, res) => {
    Users.findById(req.params.id)
    .then(user => {
        user.userImage = req.file.path || user.userImage,

        user 
            .save()
            .then(() => res.json("The User is UPDATED succesfully!"))
            .catch(err => res.status(400).json(`Error: ${err}`)); 
        }) 
    .catch(err => res.status(500).json(`Error: ${err}`));  
    console.log(req.body); 
    console.log(req.file); 

});
 

Однако, когда я тестирую код на клиенте, я получаю следующую ошибку 500: «»Ошибка: ошибка типа: не удается прочитать свойство ‘path’ из undefined». Я использую React Hooks и Axios, код ниже:

 import React, { useState, useContext } from 'react'; 
import Exit from '../cancel.svg'; 
import Modal from 'react-modal';
import { useForm } from "react-hook-form";
import axios from 'axios';
import UserContext from "../context/UserContext"; 
import { useHistory } from "react-router-dom";


Modal.setAppElement('#root');

const ProfilePicture = () => {
    const [modalIsOpen, setModalIsOpen]= useState (true);
    const { register, handleSubmit } = useForm (); 
    const [userImage, setUserImage] = useState(); 

    const onSubmit = (data) => console.log(data);

    const { userData } = useContext(UserContext); 
    const history = useHistory();


    const changeOnClick = e => {
        const users = {
            userImage
        }; 

        console.log(users); 

         axios
            .put(`http://localhost:5000/users/update/${userData.user.id}`, users)
            .then(res => console.log(res.body))
            .catch(err => {
                console.log(err); 
            }); 
            history.push("/Landing")
    } 

return(
<Modal isOpen={modalIsOpen} onRequestClose={() => setModalIsOpen(false)} className='finishBorder'> 
    <div className='border-bottom-two'>
        <img onClick= {() => setModalIsOpen(false)} className='newexitButton'src={Exit} alt='X' />
            <span className='lastThing'>One last thing! Add a profile picture</span>
    </div>
    <form onSubmit={handleSubmit(changeOnClick)} encType="multipart/form-data" >
        <div>
            <span className="dot"></span>
            <input onChange={e => setUserImage(e.target.value)} ref = {register} type='file' name='userImage' className='picUploader'/>
            {/* <button>submit</button> */}
        </div>
        <div>
            <button type='submit' className='doneButton'>Done</button>
                <div>
                    <span className='laterTwo'>I'll do this later</span>
                </div>
        </div>
    </form>
</Modal>
)

}

export default ProfilePicture; 
 

Спасибо за помощь!

Ответ №1:

То, что вы отправляете от клиента, является «поддельным путем», а не файлом. Для доступа к файлу из ввода используйте:

 setUserImage(e.target.files[0])
 

Кроме того, я думаю, что multer работает только с составными / form-данными, поэтому вы должны это проверить, но это так же просто, как:

 const formData = new FormData();
formData.append([image name], [image file]);
axios.post(`http://localhost:5000/users/update/${userData.user.id}`, formData, { 
headers: { "Content-Type": "multipart/form-data" }})
 

Комментарии:

1. Спасибо, Гастон! Ваш ответ привел меня на правильный путь; я помещаю правильный рабочий код выше