Why multer is not uploading my image in the public folder?

Viewed 43

I am creating one feature to upload images using multer . But i am not able to do so . A link is being created in the prescription but the image is not being saved in the public/images folder .

This is the jsx code.

<p>Upload Prescription</p>
      {selectedImage && (
        <div>
        <img alt="not found" width={"250px"} src={URL.createObjectURL(selectedImage)} />
        <br/>
        </div>
      )}
      <br />
     
      <br /> 
      <input
        type="file"
        name="image"
        onChange={(event) => {
          console.log('hi');
          console.log(event.target.files[0]);
          setSelectedImage(event.target.files[0]);
        }}
      />
      <button onClick={(e)=>{setSelectedImage(null)}}>
        Remove 
      </button>
    </div>
        </div>
        <button onClick={handleClick}>
            Add Record
        </button>

This is the handleClick function

const handleClick = async (e) =>{
    e.preventDefault();
    console.log(URL.createObjectURL(selectedImage));
    const recordData =
    {
      diseasename,weight,height,medicines,desc,checkdate,patientId, prescription:URL.createObjectURL(selectedImage)
    }
    try{
      const res = await axios({
        method: "POST",
        url: "http://localhost:3000/api/record/createrecord",
         data: recordData,
         withCredentials: false
        });
      console.log(res.data);
    }
    catch(err){
      console.log(err);
    }
  }

In controllers, I am setting prescription as req.file

import historyCard from "../models/historyCard.js";

export const medicalHistory = async(req,res,next) =>{
    console.log(req.file);
    try{
        // console.log(req.body);
        const newRecord = new historyCard({
            "diseasename":req.body.diseasename,
            "checkdate":req.body.checkdate,
            "weight":req.body.weight,
            "height":req.body.height,
            "desc":req.body.desc,
            "prescription":req.prescription
        })

        console.log(newRecord);
        await newRecord.save();
        res.status(200).send(newRecord);

    }catch(err){
        next(err);
    }
}

This is how i have imported multer

const storage = multer.diskStorage({
    destination: (req, file, cb) => {
      cb(null, "./public/images");
    },
    filename: (req, file, cb) => {
      cb(
        null,
        Date.now()+file.originalname
      );
    },
  });

const upload=multer({
    storage:storage,
    limits:{
        fieldSize:1024*1024*3
    }
})

const router = express.Router();
router.post('/addrecord',upload.single('image'),medicalHistory);

In database I am storing prescription as

prescription:{
        type:String,
        default: ""
    }

But the thing that is happening is , it is not being in my public folder.

1 Answers

well, you're not sending the file. You need to use FormData to send the file, and by using its .append method, not an object, with URL.createObject

You can append the file separately, as well as recordData object by stringifying it, and then parse it on the server.

Since the file is stored in a public folder, you can store path to the file as a value of prescription property. You can then add that property to the parsed recordData object on the server once the file is uploaded (and because only there can you know the file path, because of the custom filename), and then save the whole object:

try this:

on the client upload:

const handleClick = async (e) =>{
    e.preventDefault();
    console.log(selectedImage.name);
    
    // add data, without prescription
    const recordData =
    {
      diseasename,weight,height,medicines,desc,checkdate,patientId
    }

    // use FormData
    const formData = new FormData();

    // append JSON data
    formData.append('recordData', JSON.stringify(recordData));

    // append file. the name should match the one on multer: upload.single('image'),
    formData.append('image', selectedImage);

    try{
      const res = await axios({
        method: "POST",
        url: "http://localhost:3000/api/record/createrecord",
         data: formData, // send formdata
         withCredentials: false
        });
      console.log(res.data);
    }
    catch(err){
      console.log(err);
    }
  }

and on the controller parse recordData, and add file path as prescription's property value:

  const recordData = JSON.parse(req.body.recordData);

  // save only path to the file, since it's in the public folder
  recordData.prescription = req.file.path;

  console.log('recordData', recordData);

  // save..
  const newRecord = new historyCard(recordData);
Related