Link to home
Start Free TrialLog in
Avatar of Crazy Horse
Crazy HorseFlag for South Africa

asked on

uploaded image being deleted instead of old image

I have a profile photo which the user can update. What SHOULD happen is that when they upload a new photo, the database is updated and the old photo is deleted. However, what is happening is that the database is updated correctly, but the newly uploaded image is deleted meaning there is no image at all now. I also tried deleting the file synchronously using fs.unlinkSync but had the same result.

const multerStorage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, "public/img");
  },
  filename: (req, file, cb) => {
    const ext = file.mimetype.split("/")[1];
    cb(null, `hero-${Date.now()}.${ext}`);
  }
});

// test if uploaded file is an image
const multerFilter = (req, file, cb) => {
  if (file.mimetype.startsWith("image")) {
    cb(null, true);
  } else {
    // throw error here
    cb(console.log("not an image"), false);
  }
};

const upload = multer({
  storage: multerStorage,
  fileFilter: multerFilter
});
exports.uploadUserPhoto = upload.single("bgImg");

Open in new window



exports.updateHeroImg = async (req, res) => {
  const updateId = "5d13b3c6dd57c43828ed5a7a";
  if (req.file) bgImgNew = req.file.filename;
  //find current image name in database
  const hero = await Hero.findById(updateId);
  if (!hero) return;

  // helper function to delete files
  fileHelper.deleteFile("public/img/" + hero.bgImg);

  // set new db record image name
  hero.bgImg = bgImgNew;

  // update database
  const result = await hero.save();
  res.status(200).send("image uploaded");
};

Open in new window

Helper delete function

const fs = require("fs");

const deleteFile = filepath => {
  fs.unlink(filepath, err => {
    if (err) {
      throw err;
    }
  });
};

exports.deleteFile = deleteFile;

Open in new window


My route:

router.post("/", heroController.uploadUserPhoto, heroController.updateHeroImg);

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of leakim971
leakim971
Flag of Guadeloupe image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Crazy Horse

ASKER

Thanks for that. I am still having the same issue though. I have updated my original question with my upload code using multer. Perhaps the issue is there.
I have changed the code to not delete the image and added console log to some of the steps:

exports.updateHeroImg = async (req, res) => {
  const updateId = "5d13b3c6dd57c43828ed5a7a";
  const hero = await Hero.findById(updateId);
  if (!hero) return;

  console.log("title is " + hero.title + " and image is " + hero.bgImg);
 

  if (req.file) bgImgNew = req.file.filename;
  console.log("the newly uploaded file is " + bgImgNew);
  hero.bgImg = bgImgNew;

  const result = await hero.save();
  console.log("updated database");
  res.status(200).send("image uploaded");
};

Open in new window




title is Some title X and image is hero-1565280744900.jpeg
the newly uploaded file is hero-1565280744900.jpeg
updated database

Open in new window


If I remove this line:

hero.bgImg = bgImgNew;

Open in new window


Then the console.log info is correct in that I have 2 different file names. But now the database is not updated. So, at least I managed to pinpoint the line that is causing the issue, now just need to resolve the issue.
I have found the issue but I don't know why it is an issue.

If I remove this line:

res.status(200).send("image uploaded");

Open in new window


everything works as expected except that I don't get my success message so the user won't actually know that the record was updated and everything went okay.

It seems that the line of code above makes the request happen twice which was why the image was being deleted after being uploaded but why?
exports.updateHeroImg = async (req, res) => {
  const updateId = "5d13b3c6dd57c43828ed5a7a";
  const hero = await Hero.findById(updateId);
  if (!hero) return;

  console.log("title is " + hero.title + " and image is " + hero.bgImg);
 

  if (req.file) bgImgNew = req.file.filename;
  console.log("the newly uploaded file is " + bgImgNew);
  hero.bgImg = bgImgNew;

  const result = await hero.save();
  console.log("updated database");
  res.status(200).send("image uploaded");
};

// let's sasy we're at the last line here
// end of connexion here
// and you did not send back anything to browser
// the conversation with you browser and your server is broken

Open in new window


what about :

exports.updateHeroImg = async (req, res) => {
  const updateId = "5d13b3c6dd57c43828ed5a7a";
  const hero = await Hero.findById(updateId);
  if (!hero) return;

  console.log("title is " + hero.title + " and image is " + hero.bgImg);
 

  if (req.file) bgImgNew = req.file.filename;
  console.log("the newly uploaded file is " + bgImgNew);
  hero.bgImg = bgImgNew;

  const result = await hero.save();
  console.log("updated database");
  
};

res.status(200).send("image upload in progress...");

Open in new window

Soooo.. After spending time debugging I finally realised that this has nothing to do with node.js which I initially thought that was where the problem was. It turns out it was on the React side with the Filepond package. I had a callback which sent the request but the package was already sending the same request without me knowing it. That is why it was uploading the file and deleting it straight away. I removed my own callback and now it works fine.
Although the answer I accepted wasn't actually the solution to my problem, it is helpful information that I can use going forward, thank you.