skip to Main Content

SO I’m trying to send an image from the react front end to the node.js back end but when I send a .jpg to the back end and I ask there what tpye it is sais it’s a jpeg while multer still thinks its a jpg so it the sharp functions I do on it don’t work anymore and give an error because they can’t find the file.

I tried using by both instances where I need the file type (where multer saves it and where I declaire the imput by for sharp) but that didn’t work. here is the code for the front end:

function App() {
  const [image, setImage] = useState("");
  function handleImage(e) {
    console.log(e.target.files);
    setImage(e.target.files[0]);
  }
  function handleApi() {
    const formData = new FormData();
    formData.append("image", image);
    formData.append("pfp", "yes");
    formData.append("filetype", image.type )
    console.log('hello')
    console.log(image)
    console.log(formData)
    axios
      .post("http://localhost:3001/users/editprofile/1", formData, {
        headers: {
          "Content-Type": "multipart/form-data",
        },
      })
      .then((res) => {
        console.log(res);
      });
  }
  return (
    <div>
      <input type="file" name="file" onChange={handleImage} />
      <button onClick={handleApi}>submit</button>
    </div>
  );
}`

and here is the code for the back end:

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "images/temp");
  },
  filename: function (req, file, cb) {
    const id = req.params.id;
    let extention = path.extname(file.originalname);
    cb(null, `pfp_${id}` + extention);
  },
});

router.post("/editprofile/:id", upload.single("image"), async (req, res) => {
  const id = req.params.id;
  const { pfp, bio, filetype } = req.body;
  console.log(bio);
  console.log(req.body);
  if (pfp) {
    const typetemp = filetype.split("/");
    const type = typetemp[typetemp.length - 1];

    var imput = path.join(
      __dirname,
      "..",
      "images/temp",
      "pfp_" + id + "." + type
    );
    var output = path.join(__dirname, "..", "images/temp", id + "png.png");
    var newimage = path.join(
      __dirname,
      "..",
      "images/profile_pictures",
      "pfp_" + id + ".png"
    );

    try {
      const metadata = await sharp(imput).metadata();
      if (metadata.format != "png") {
        await sharp(imput).toFormat("png", { palette: true }).toFile(output);
      } else {
        await sharp(imput).toFile(output);
      }
      if (metadata.height > metadata.width) {
        var topcut = Math.round((metadata.height - metadata.width) / 2);
        await sharp(imput)
          .extract({
            width: metadata.width,
            height: metadata.width,
            left: 0,
            top: topcut,
          })
          .toFile(newimage);
      } else if (metadata.height < metadata.width) {
        var leftcut = Math.round((metadata.width - metadata.height) / 2);
        console.log(leftcut);
        await sharp(imput)
          .extract({
            width: metadata.height,
            height: metadata.height,
            left: leftcut,
            top: 0,
          })
          .toFile(newimage);
      }
      const metadatanew = await sharp(newimage).metadata();
      console.log(metadatanew);
      var newpfp = id + ".png";
    } catch (error) {
      console.log(error);
    }
  }

I get the following error in the console when I try to upload a jpg:

[Object: null prototype] { pfp: 'yes', filetype: 'image/jpeg' }
[Error: Input file is missing: D:programmeerstuffjavascriptpwsversion 0.0.1serverimagestemppfp_1.jpeg]

and this is the picture I tried to upload: (don’t mind what’s on it it was just the first image I saw when I clicked choose file XD)
photo I tried to upload

2

Answers


  1. The issue you are experiencing is related to the MIME type of the image you are trying to upload. Specifically, the file extension of the image is .jpg, while its MIME type is image/jpeg. When you are handling the image in your backend, you are using the MIME type jpeg instead of file extension .jpg.

    To resolve this issue, one possible solution is to avoid using the MIME type in your back-end altogether and rely on the file extension instead. This way you can ensure that the correct file type is being used and that the image can be accessed without issue.

    Also it’s important to ensure that the correct MIME type is used when sending the image to the client to ensure that it is displayed correctly in the browser.

    Login or Signup to reply.
  2. The problem is there is no image/jpg mime type, and you’re creating file extension with the mime type, which is always image/jpeg, so you’ll always end up with .jpeg file extension.

    Solution would be to send file extension from the frontend, instead of mime type:

    // get file extension, maybe also add extra check to ensure there is one   
    const filetype = image.name.split('.').pop();
    
    formData.append("filetype", filetype )
    

    And on the server you should check if file exists (and add extra checks, if needed).

    Try this, add in on the server, where you set type and imput (no need to set type, now fileType contains extension from the frontend:

    const fs = require('fs');
    
    let imput = path.join(
              __dirname,
              "..",
              "images/temp",
              "pfp_" + id + "." + filetype
            );
    
    
    if(!fs.existsSync(imput)) {
    
            
            // no file, return error
    
    
    }
    

    EDIT

    or, simply read the file from the req.file.path, instead of passing and constructing extension, and to make sure the file is uploaded, read req.file, to make sure it exists before passing it to sharp:

    if (pfp && req.file) {
    
        const imput = path.join(__dirname, "..", req.file.path);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search