React Native安卓端通过Axios传图片至Node.js后端,Multer无法识别文件
React Native(安卓)上传图片至Express后端,Multer无法识别文件
我正尝试从React Native前端(安卓手机)向Node.js/Express后端发送图片,图片需经Multer处理后上传至Cloudinary(此步骤与问题无关)。用Postman测试一切正常,但通过Axios(也试过fetch)发起POST请求时失败,Multer识别不到请求里的文件。
前端代码
const uploadProfileImage = async ()=>{ const formData = new FormData(); //console.log(profileImage); const image = { uri: profileImage, type: mime.getType(profileImage), name: new Date() + "_pfp", } as any formData.append('pfp', { uri: profileImage, type: mime.getType(profileImage), name: new Date() + "_pfp", }); try { const res = await client.post('/upload-pfp', formData, {headers:{ Accept: 'application/json', 'Content-Type': 'multipart/form-data', authorization: 'JWT ...', }}); console.log(res.data); } catch (error) { console.error('Upload failed:', { message: error.message, status: error.response?.status, data: error.response?.data }); } }
后端POST请求处理器
router.post('/upload-pfp', isAuth, uploads.single('pfp'), uploadPfp)
Multer配置
const multer = require('multer'); const storage = multer.diskStorage({}); const fileFilter = (req, file, cb)=>{ console.log("first") if(file.mimetype.startsWith('image')){ cb(null, true); }else{ cb('Invalid image file', false); } } const uploads = multer({storage, fileFilter})
授权中间件(供参考)
exports.isAuth = async(req, res, next)=>{ if(req.headers && req.headers.authorization){ const token = req.headers.authorization.split(' ')[1]; try { const decode = jwt.verify(token, process.env.JWT_SECRET); const user = await User.findById(decode.userId); if(!user){ return res.json({success: false, message: "Unauthorized access"}); } req.user = user; next(); } catch (error) { if(error.name == 'JsonWebTokenError'){ return res.json({success: false, message: "Unauthorized access"}); } if(error.name == 'TokenExpiredError'){ return res.json({success: false, message: "Session expired, try signing in"}); } res.json({success: false, message: "Internal server error"}); } } else { res.json({success: false, message: "Unauthorized access"}) } }
解决办法
1. 修复React Native FormData文件格式问题
React Native的FormData对文件对象的要求和Web端不同,不能直接传普通对象,且不要手动设置Content-Type头(Axios会自动根据FormData生成正确的multipart边界)。另外安卓端的uri需要去掉file://前缀:
修改前端代码:
import { Platform } from 'react-native'; const uploadProfileImage = async ()=>{ const formData = new FormData(); // 处理安卓端uri格式 const fixedUri = Platform.OS === 'android' ? profileImage.replace('file://', '') : profileImage; formData.append('pfp', { uri: fixedUri, type: mime.getType(fixedUri) || 'image/jpeg', // 兜底默认图片类型 name: `${Date.now()}_pfp.jpg` }); try { const res = await client.post('/upload-pfp', formData, { headers: { authorization: 'JWT ...', // 移除手动设置的Content-Type } }); console.log(res.data); } catch (error) { console.error('Upload failed:', { message: error.message, status: error.response?.status, data: error.response?.data }); } }
2. 后端加日志排查
在isAuth中间件末尾或uploadPfp函数开头添加日志,确认请求是否携带文件:
// 在isAuth的next()前添加 console.log('请求体:', req.body); console.log('接收的文件:', req.file);
3. 确认安卓权限配置
检查AndroidManifest.xml是否添加了图片读取权限:
<!-- Android 12及以下 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android 13+ --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
4. 兜底MIME类型
如果mime.getType(profileImage)返回undefined,会触发Multer的fileFilter拒绝文件,所以必须设置兜底值,比如上面代码中的'image/jpeg'。
内容的提问来源于stack exchange,提问作者NotCoding
相关产品推荐
相关产品推荐

