Search code examples
javascriptnode.jsreactjsaxiosmulter

req.file is undefined when uploading image from front end


I have checked other similar post but its still not working: Its giving me undefined when console.log. I also defined the multer middleware according to other posts so I don't know what happened. But when I upload an image through postman it works with returning an 201as expected. Any help is appreciated!

ReactJS function:

const UploadImageToBackend = async () => {
  console.log(UploadedImage) //UploadedImage is something like /Users/.../.jpg
  let formData = new FormData()
  formData.append('profile', 
    {name : new Date() + "_profile", uri: UploadedImage, type:'image/jpg'})
  
  try{
    const res = await client.post('/upload-avatar',formData, {
      headers:{
        Accept : 'application/json',
        authorization: 'JWT some JWT'
      },
    })
    console.log(res.data)
  }catch(error){
    console.log(error.response.data) //gives "Error while uploading Image, try after some time" error
  }
  
}

Backend Routes:

const fileFilter = (req,file,callback) => {
    if (file.mimetype.startsWith('image')){
        callback(null,true)
    }else{
        callback('invalid image file', false)
    }
}
const storage = multer.diskStorage({})
const uploads = multer({storage, fileFilter})
router.post('/upload-avatar',isAuth, uploads.single('profile'),uploadProfile)

backend upload function (to Cloudinary)

exports.uploadProfile = async (req,res)=>{
    const user = req.user
    if (!user){
        return res.status(401).json({success:false,message:"unauthorized access!"})
    }else{
        console.log(req.file.path) //undefined
        try{
            const upload_result = await cloudinary.uploader.upload(req.file.path, {
                public_id: `${user._id}_profile`,
                width:500,
                height:500,
                crop: 'fill'
            })
            await User.findByIdAndUpdate(user._id, {avatar: upload_result.url})
            res.status(201).json({success:true,message: "Profile picture successfully uploaded"})
            
        }catch (error){
            res.status(500).json({success:false,message: 
        "Error while uploading Image, try after some time"})
        }
        
        
    }
}

Solution

  • create this function (to upload into Cloudinary), e.g. "lib/cloudinary.js" and add this code:

    import cloudinary from "cloudinary";
    
    cloudinary.config({
       cloud_name: "YOUR_CLOUD_NAME",
       api_key: "YOUR_API_KEY",
       api_secret: "YOUR_API_SECRET",
    });
    
    const upload = {};
    
    upload.subir = async (file) => {
      try {
        const res = await cloudinary.uploader.upload(file);
        // return the secure url
        return res.secure_url;
      } catch (error) {
        return error;
      }
    }
    
    export default upload;
    

    Now in your controller, e.g. add this code, do not forget to install express-fileupload:

    import cloudinary from "../lib/cloudinary.js";
    
    const upload = {};
    
    upload.uploadProfile = async (req, res) => {
       const a_file = await cloudinary.subir(req.files.a_file.tempFilePath);
       // show the secure url, e.g.: 
       // https://res.cloudinary.com/xx/image/upload/yy/winter.jpg
       console.log(a_file);
       // ... more code
    }
    
    export default upload;
    

    Now in your main application e.g., "app.js" add this code to use the express middleware for uploading files:

    import express from 'express';
    import fileUpload from 'express-fileupload';
    
    const app = express();
    
    app.use(express.json());
    app.use(express.urlencoded({extended: true}));
    app.use(fileUpload({useTempFiles: true}));
    // ...  more code
    

    Test the function using postman and the file has been uploaded
    testing the function

      NOTE: Do not forget and remember that this only is an alternative, exist anothers many ways i hope you understand and i hope it works for you