Uploading React - Node image(s) to Cloudinary

Viewed 67

Has anyone uploaded an image using Node, React, Antd library to cloudinary? I'm getting an error saying that the file is missing. I'm not sure if I should be sending the entire file object or just the name. I have sent the thumburl (sometimes it works others it doesn't there has to be something I'm doing wrong).

This is my backend

const uploadImage = async (req, res) => {
try {
    const result = await cloudinary.uploader.upload(req.body.image, {
        public_id: `${Date.now()}`,
        resource_type: 'auto' //jpeg or png
    });

    res.json({
        public_id: result.public_id,
        url: result.secure_url
    });
} catch (error) {
    console.log(error);
    res.status(400).send(error)
}}

This is my frontend:

const Uploader = () => {

    const { token } = useSelector(state => state.user);

    const handleChange = ({file}) => {   

        console.log(file)

        axios.post(`${process.env.REACT_APP_API}/uploadImages`, {file}, {
            headers:{
                authtoken: token
            }
        })
        .then(res => console.log(res))
        .catch(err => console.log(err))
    };
    return (
        <Upload
            listType="picture"
            showUploadList
            onChange={handleChange}
        >
            <Button>Upload</Button>
        </Upload>
  
    )
}

export default Uploader

IDK why the onChange triggers 3 times when it has worked I've sent the thumbUrl and it uploads 3 times, I have seen that I can use beforeUpload but I believe this works before uploading. I want to upload, preview the image and sending it to the server and then send it to my Form Component to add it to the values I have there

Anyone who has already uploaded could help or any ideas would be appreciated?

3 Answers

When it comes to the file not uploading properly, I am guessing it is because the res.body.image isn't the actual file. I would look at what the value is there. I would guess you are missing a middleware. As far as your frontend issue, I'm still a little unclear about what the issue you are having exactly is. For an example of a clean frontend upload I would check out https://codesandbox.io/embed/jq4wl1xjv. You could also consider using the upload widget which will handle the preview as well as give you some easy editing options. https://cloudinary.com/documentation/upload_widget

I was able to figure it out, indeed there is a need of a middleware, I used formidable on the routes of my backend

router.post('/uploadImages', authCheck, adminCheck, formidable({maxFileSize: 5 * 1024 * 1024}), imageUpload);

And fixed the controller

const imageUpload = async (req, res) =>{
    try {
        //console.log('req files:', req.files.file.path)
        const result = await cloudinary.uploader.upload(req.files.file.path, {
            public_id: `${Date.now()}`,
            resource_type: 'auto'
        });

        res.json({
            public_id: result.public_id,
            url: result.secure_url
        })
    } catch (error) {
        console.log(error)
    }
}

As far as the Frontend goes. Ant designs component takes an action that makes the POST to the backend, and it also takes headers if needed (in my case it takes an authtoken for firebase).

When the image is uploaded it makes the POST to the backend based on the "action". The response will bring back the "FileList" with the upload URL to access it.

        <Upload
          listType="picture"
          showUploadList
          multiple   
          action={`${process.env.REACT_APP_API}/uploadImages`}
          headers={{authtoken: token}}
        >
          <Button>Upload Images</Button>
        </Upload>

I hope this helps somebody else too

I tried this and it's worked for me. Here I used Multer middleware for handling form data(for uploading files).

I used this route,

router.post('/uploadImages', authMiddleware, multer.single("image"), imageUpload);

Corrected controller,

    try {
        let result;
        if (req.file) {
        result = await cloudinary.uploader.upload(req.files.file.path, {
            public_id: `${Date.now()}`,
            resource_type: 'auto'
        });
    }
        res.json({
            public_id: result.public_id,
            url: result.secure_url
        })
    } catch (error) {
        console.log(error)
    }
}

//Multer config file,


const multer = require("multer");
const path = require("path");

module.exports = multer({
  storage: multer.diskStorage({}),
  fileFilter: (req, file, cb) => {
    let ext = path.extname(file.originalname);
    if (
      ext !== ".jpg" &&
      ext !== ".jpeg" &&
      ext !== ".png" &&
      ext !== ".PNG" &&
      ext !== ".JPG" &&
      ext !== ".JPEG"
    ) {
      cb(new Error("File type is not supported"), false);
      return;
    }
    cb(null, true);
  },
});



Related