React Native Expo应用上传头像存储至Node.js后端的问题咨询
问题修复方案
1. 现存问题梳理
- 前端Axios参数错误:Axios发送POST请求时,请求体参数为
data不是body,且手动设置multipart/form-data头会丢失边界信息,不需要手动设置,Axios会自动处理 - 字段名不匹配:前端FormData提交的字段是
profilePicture,后端错误从req.body取image字段,且multipart类型的请求不能直接从req.body取文件,需要用专门的解析中间件 - 后端逻辑错误:你拿到的file://路径是用户客户端本地的缓存路径,后端服务器根本不可能访问到这个路径,fs.move当然会报错,你需要先解析前端上传的文件流,再存储到服务端本地
- 额外的小错误:Authorization头里多写了一个$,应该是
Bearer ${token}不是Bearer$${token}
2. 后端修复步骤
首先安装multer中间件,专门用来处理multipart/form-data类型的文件上传请求:
npm install multer
然后修改后端接口代码:
const multer = require('multer'); const path = require('path'); const fs = require('fs-extra'); // 配置multer存储规则 const storage = multer.diskStorage({ destination: function (req, file, cb) { // 确保存储目录存在 const uploadDir = path.resolve(__dirname, "../PostImages"); fs.ensureDirSync(uploadDir); cb(null, uploadDir); }, filename: function (req, file, cb) { // 自定义文件名,避免重名,可自行修改命名规则 const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); cb(null, 'avatar-' + uniqueSuffix + path.extname(file.originalname)); } }); // 单文件上传,对应前端的字段名profilePicture const upload = multer({ storage: storage }).single('profilePicture'); // 上传接口 app.post('/userImg', upload, async (req, res) => { try { // req.file就是解析完成的文件信息 console.log('文件存储成功', req.file.path); // 如果要存数据库,直接把req.file.path或者你定义的访问路径存到用户表对应的头像字段即可 res.status(200).json({ code: 0, msg: '上传成功', avatarPath: req.file.filename }); } catch (err) { console.error(err); res.status(500).json({code: 1, msg: '上传失败'}); } });
你之前写的fs.move相关代码可以直接删除,multer已经完成了文件存储的逻辑。
3. 前端修复步骤
3.1 修复请求发送代码
const uploadUserImage = (dispatch) => { return async ({ data }) => { console.log(data); const token = await AsyncStorage.getItem("token"); try { await axios({ method: "post", url: "http://localhost:5000/userImg", headers: { // 去掉多余的$ Authorization: `Bearer ${token}`, // 不要手动设置Content-Type,axios会自动携带边界参数 }, // 把body改为data data: data, }); } catch (err) { console.log(err); } }; };
3.2 补充Android平台配置(遇到权限问题时添加)
在app.json里添加Android的文件访问权限:
{ "expo": { "android": { "permissions": ["READ_EXTERNAL_STORAGE", "WRITE_EXTERNAL_STORAGE"] } } }
如果你使用Expo ImagePicker,记得先请求用户的媒体库权限再选择图片。
4. 额外优化建议
如果要让前端能访问到上传的头像,可以在后端配置静态资源托管:
app.use('/post-images', express.static(path.resolve(__dirname, "../PostImages")));
之后前端就可以通过http://你的服务器地址:5000/post-images/文件名访问到头像。
内容的提问来源于stack exchange,提问作者Filipe Mota
相关产品推荐
相关产品推荐

