Expo Go无法上传Base64编码图片:安卓正常iOS端异常
问题排查与解决方案
核心矛盾:前端发送格式与后端接收方式不匹配
upload.single('photo')是multer专门处理multipart/form-data格式的文件上传的中间件,它不会解析普通字符串字段(包括Base64格式的字符串)。Android上能正常工作大概率是偶然情况,iOS的Expo Go在FormData处理上更严格,直接暴露了这个格式不匹配的问题。
具体排查步骤与修复方案
1. 修正前端请求格式(最可能解决问题)
如果直接把Base64字符串作为普通字段传,multer根本识别不了。正确做法是把Base64转成Blob,再作为文件字段添加到FormData里:
async function logPicture(base64String) { // 先去掉Base64前缀(比如data:image/jpeg;base64,) const pureBase64 = base64String.replace(/^data:image\/\w+;base64,/, ''); // 把Base64转成Blob const byteChars = atob(pureBase64); const byteNumbers = new Array(byteChars.length); for (let i = 0; i < byteChars.length; i++) { byteNumbers[i] = byteChars.charCodeAt(i); } const byteArray = new Uint8Array(byteNumbers); const blob = new Blob([byteArray], { type: 'image/jpeg' }); // 按实际图片类型调整 const formData = new FormData(); formData.append('photo', blob, 'captured.jpg'); // 第三个参数是文件名,可选 formData.append('local', '你的local参数值'); // 保留原有参数 try { const res = await fetch('你的后端接口地址', { method: 'POST', body: formData, // 注意:iOS上别手动加Content-Type,浏览器会自动带boundary参数,手动加会导致multer识别失败 }); const result = await res.json(); console.log('上传结果:', result); } catch (err) { console.error('上传失败:', err); } }
2. 用Expo原生文件系统处理(兼容iOS更稳定)
如果上面的Blob方式还是有问题,试试用expo-file-system把Base64转成本地临时文件再上传:
import * as FileSystem from 'expo-file-system'; async function logPicture(base64String) { const tempPath = `${FileSystem.cacheDirectory}captured.jpg`; // 把Base64写入临时文件 await FileSystem.writeAsStringAsync( tempPath, base64String.replace(/^data:image\/\w+;base64,/, ''), { encoding: FileSystem.EncodingType.Base64 } ); const formData = new FormData(); formData.append('photo', { uri: tempPath, name: 'captured.jpg', type: 'image/jpeg' }); formData.append('local', '你的local参数值'); try { const res = await fetch('你的后端接口地址', { method: 'POST', body: formData, headers: { 'Accept': 'application/json' } }); const result = await res.json(); console.log('上传结果:', result); } catch (err) { console.error('上传失败:', err); } }
3. 后端加日志验证请求
在后端multer中间件前加日志,确认请求格式是否正确:
app.post('/upload', (req, res, next) => { console.log('请求Content-Type:', req.headers['content-type']); next(); }, upload.single('photo'), (req, res) => { console.log('收到的文件:', req.file); console.log('收到的local参数:', req.body.local); // 后续保存逻辑 });
如果Content-Type里没有boundary=xxx,说明前端请求格式错误,必须调整FormData的发送方式。
4. 检查iOS权限配置
确保Expo应用在iOS上申请了必要权限,虽然拍照成功,但权限不足可能影响文件处理。在app.json里添加:
{ "expo": { "ios": { "infoPlist": { "NSCameraUsageDescription": "需要访问相机拍照", "NSPhotoLibraryAddUsageDescription": "需要访问相册保存照片" } } } }
总结
本质问题是前端发送的Base64字符串和后端multer期望的文件上传格式不匹配,iOS的Expo Go没像Android那样“兼容”错误格式。通过把Base64转成Blob或临时文件,用标准multipart/form-data格式发送,就能解决问题。
内容的提问来源于stack exchange,提问作者Mathias
相关产品推荐
相关产品推荐

