解决Axios上传jpg图片时后端识别为jpeg导致Sharp报错问题
问题:JPG图片上传后Sharp处理找不到文件的问题
我从React前端向Node.js后端发送.jpg图片,后端识别文件类型为jpeg,但multer仍按原后缀将其保存为.jpg,导致后续Sharp处理图片时因找不到文件报错。我尝试在multer保存文件和Sharp定义输入路径的两处统一文件类型,但未解决问题。
前端代码
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> ); }
后端代码
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); } } });
报错信息
[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]
解决方法
问题核心是multer保存的文件名后缀和Sharp读取的后缀不一致:multer用了原文件的.jpg后缀,而Sharp根据前端传来的filetype拼接成了.jpeg,导致路径错误。
直接使用multer上传后提供的真实文件路径是最可靠的方案,完全避免后缀匹配问题:
- 后端中,multer上传完成后会把文件的完整信息存入
req.file对象,直接取req.file.path作为Sharp的输入路径即可。 - 无需前端传递
filetype字段,也不用手动拼接文件名,彻底消除路径不匹配的可能。
修改后的后端关键代码:
router.post("/editprofile/:id", upload.single("image"), async (req, res) => { const id = req.params.id; const { pfp, bio } = req.body; if (pfp) { // 直接使用multer保存的真实文件路径 const inputPath = req.file.path; var output = path.join(__dirname, "..", "images/temp", `${id}_temp.png`); var newimage = path.join( __dirname, "..", "images/profile_pictures", `pfp_${id}.png` ); try { const metadata = await sharp(inputPath).metadata(); // 后续逻辑保持不变,仅替换输入路径为inputPath if (metadata.format !== "png") { await sharp(inputPath).toFormat("png", { palette: true }).toFile(output); } else { await sharp(inputPath).toFile(output); } if (metadata.height > metadata.width) { var topcut = Math.round((metadata.height - metadata.width) / 2); await sharp(inputPath) .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); await sharp(inputPath) .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); } } });
同时前端可以删除formData.append("filetype", image.type)这一行代码,该字段已不再需要。
内容的提问来源于stack exchange,提问作者Tijmi
相关产品推荐
相关产品推荐

