Multer上传图片时Axios请求req.file为undefined的问题解决
Multer图片上传:Postman正常但Axios请求时req.file为undefined(400错误)
问题现象
- Multer实现的图片上传功能,通过Postman测试完全正常
- 前端使用Axios发送请求时,后端
req.file始终为undefined,但req.body能正确获取到预期数据 - 前端收到400错误响应,后端日志输出"Please upload an image"
相关代码
Multer配置(multer.ts)
import { Request, Response, NextFunction } from "express"; import multer from "multer"; const storage = multer.diskStorage({ destination: "uploads/", filename: (req, file, cb) => { const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9); cb(null, uniqueSuffix); }, }); const uploads = multer({ storage: storage, limits: { fileSize: 1024 * 1024 * 5, files: 1, fieldSize: 1024 * 1024 * 5, }, fileFilter: (req, file, cb) => { if (file.mimetype === "image/jpeg" || file.mimetype === "image/png") { cb(null, true); } else { cb(new Error("File type not supported!")); } }, }); interface RequestWithUser extends Request { user?: { id: number; email: string; }; } export function uploadImage( req: RequestWithUser, res: Response, next: NextFunction ) { uploads.single("image")(req, res, (err) => { if (err instanceof multer.MulterError) { console.error("MulterError =>", err.message); return res.status(400).json({ message: err.message }); } if (err) { console.error("MulterError =>", err.message); return res.status(400).json({ message: err.message }); } if (!req.file) { console.error("Please upload an image"); return res.status(400).json({ message: "Please upload an image" }); } console.log("req.body MWW =>", req.body); console.log("req.file MWW =>", req.file); next(); }); }
路由配置
router.post( "/create-image", authorize, uploadImage, createImageController.createImage );
原Axios请求代码
const handleGenerateImage = async (prompt: string, image: string) => { const formData = new FormData(); for (const [key, value] of Object.entries({ prompt, image })) { formData.append(key, value as string | Blob); } console.log("formData", formData); try { const result = await axios.post( "http://localhost:5000/api/create-image", formData, { responseType: "json", headers: { Accept: "multipart/form-data", "Content-Type": "multipart/form-data", Authorization: `Bearer ${TOKEN}`, }, } ); console.log("result", result); return result; } catch (error) { console.log("error", error); return; } };
错误信息与日志
- 前端错误日志:
error [AxiosError: Request failed with status code 400] - FormData日志:
formData {"_parts": [["prompt", "Superman"], ["image", "file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540anonymous%252FstickerAI-4f69cda2-177b-4e6a-9b97-2784a47b4c88/ImagePicker/2fcasdf1-30f5-4149-89a1-0304b7b3acfc.jpeg"]]} - 后端返回响应:
{ "_bodyBlob":{ "_data":{ "__collector":[ "Object" ], "blobId":"e40a7871-51f9-4678-a309-e467bcdbab3e", "offset":0, "size":36 } }, "_bodyInit":{ "_data":{ "__collector":[ "Object" ], "blobId":"e40a7871-51f9-4678-a309-e467bcdbab3e", "offset":0, "size":36 } }, "bodyUsed":false, "headers":{ "map":{ "access-control-allow-origin":"*", "connection":"keep-alive", "content-length":"36", "content-type":"application/json; charset=utf-8", "date":"Mon, 29 Apr 2024 08:56:49 GMT", "etag":"W/\"24-RuEUrN0QtPlwvGJylleayGNbKK0\"", "keep-alive":"timeout=5", "x-powered-by":"Express" } }, "ok":false, "status":400, "statusText":"", "type":"default", "url":"http://localhost:5000/api/create-image" }
已尝试的无效方案
- 从
req.body提取数据手动赋值给req.file - 改用
req.files数组接收文件 - 移除请求头中的
Content-Type字段 - 调整Express的bodyParser配置
解决方案
问题根源在于前端仅传入了图片的URI字符串,Multer无法将普通字符串识别为文件。改为传入包含name、type、uri的完整文件对象,并将URI转为Blob后再加入FormData即可解决。
调整后的Axios请求示例
const handleGenerateImage = async (prompt: string, image: {name: string, type: string, uri: string}) => { const formData = new FormData(); // 将图片URI转为Blob(以Expo环境为例) const fileResponse = await fetch(image.uri); const imageBlob = await fileResponse.blob(); // 正确添加文件到FormData,指定文件名 formData.append('image', imageBlob, image.name); formData.append('prompt', prompt); try { const result = await axios.post( "http://localhost:5000/api/create-image", formData, { responseType: "json", headers: { Authorization: `Bearer ${TOKEN}`, // 无需手动设置Content-Type,浏览器会自动生成带boundary的正确头 }, } ); console.log("result", result); return result; } catch (error) { console.log("error", error); return; } };
关键说明
- 原请求中
image字段是字符串类型的URI,FormData仅将其作为普通文本字段提交,Multer无法解析为文件,因此req.file为undefined,触发后端的400校验 - 转为Blob后,FormData会按照文件格式封装数据,Multer能正常识别并解析出
req.file
内容的提问来源于stack exchange,提问作者OzturkS
相关产品推荐
相关产品推荐

