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:\programmeerstuff\javascript\pws\version 0.0.1\server\images\temp\pfp_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)
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);