React-Native向Express(TypeScript)后端传递FormData失败求助
React Native 向 Express(TypeScript) 发送 FormData 后端接收不到文件的问题
我正尝试从React-Native应用向Express(全程使用TypeScript)后端发送FormData,但所有尝试均未奏效。前端API中可以正常打印FormData数据,但后端控制器无法接收到任何内容。以下是相关代码:
客户端代码
const handlePickImage = async () => { try { const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, allowsEditing: true, aspect: [1, 1], quality: 1, }); if (!result.canceled) { const uri = result.assets[0].uri; setProfileImage(uri); const formData = new FormData(); const fileName = uri.split('/').pop(); const response = await fetch(uri); const blob = await response.blob(); formData.append('profileImage', blob, fileName || 'profile_image.jpg'); await updateProfilePicture(formData, user.uid); } } catch (error) { console.error('Error picking image:', error); } };
前端API代码
export const updateProfilePicture = async (profilePicture: FormData, userId: string) => { try { console.log("Profile picture: ", profilePicture) const response = await fetch(`${API_URL}/user/updateprofilepicture/${userId}`, { method: 'POST', headers: { Accept: 'application/json', }, body: profilePicture, }); if (!response.ok) { throw new Error('Failed to update profile picture'); } const data = await response.json(); console.log('Profile image uploaded successfully:', data); } catch (error) { console.error('Error updating profile picture:', error); } };
后端路由代码
const multer = require('multer'); const express = require('express'); const router = express.Router(); const storage = multer.memoryStorage(); const upload = multer({ storage: storage }); router.post('/updateprofilepicture/:userId', upload.single('profileImage'), updateProfilePicture);
控制器代码
import { Multer } from 'multer'; export const updateProfilePicture = async (req: Request, res: Response) => { try { const userId = req.params.userId; const file = req.file; if (!file) { return res.status(400).json({ error: 'No file uploaded' }); } const imageUrl = await uploadProfileImage(userId, file); res.status(200).json({ imageUrl }); } catch (error) { console.error('Error in updateProfilePicture controller:', error); res.status(500).json({ error: 'Error uploading profile picture' }); } };
问题排查与解决方法
1. 移除手动设置的 Accept 头
发送FormData时,React Native会自动生成包含boundary的Content-Type: multipart/form-data头,手动设置Accept: 'application/json'会干扰后端对请求的解析逻辑。
修改后的前端API代码:
export const updateProfilePicture = async (profilePicture: FormData, userId: string) => { try { console.log("Profile picture: ", profilePicture) const response = await fetch(`${API_URL}/user/updateprofilepicture/${userId}`, { method: 'POST', body: profilePicture, }); if (!response.ok) { throw new Error('Failed to update profile picture'); } const data = await response.json(); console.log('Profile image uploaded successfully:', data); } catch (error) { console.error('Error updating profile picture:', error); } };
2. 适配React Native的FormData文件处理
React Native的FormData对Blob支持有限,建议直接使用图片uri构建文件项,避免Blob转换带来的兼容性问题:
修改后的客户端代码:
const handlePickImage = async () => { try { const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, allowsEditing: true, aspect: [1, 1], quality: 1, }); if (!result.canceled) { const uri = result.assets[0].uri; setProfileImage(uri); const formData = new FormData(); const fileName = uri.split('/').pop(); // 直接传入uri对象,指定文件名和类型 formData.append('profileImage', { uri, name: fileName || 'profile_image.jpg', type: 'image/jpeg' // 根据实际图片类型调整,如image/png } as any); await updateProfilePicture(formData, user.uid); } } catch (error) { console.error('Error picking image:', error); } };
3. 统一后端模块规范
后端路由使用CommonJS(require),控制器使用ESModule(import),可能导致模块加载异常。TypeScript项目建议统一使用ESModule:
修改后的后端路由代码:
import multer from 'multer'; import express from 'express'; import { updateProfilePicture } from '../controllers/your-controller-path'; // 替换为实际控制器路径 const router = express.Router(); const storage = multer.memoryStorage(); const upload = multer({ storage: storage }); router.post('/updateprofilepicture/:userId', upload.single('profileImage'), updateProfilePicture); export default router;
4. 添加请求日志排查
在路由中添加日志,确认请求头是否正确:
router.post('/updateprofilepicture/:userId', (req, res, next) => { console.log('Request Content-Type:', req.headers['content-type']); next(); }, upload.single('profileImage'), updateProfilePicture);
确认日志中存在multipart/form-data; boundary=xxx格式的Content-Type,否则说明前端请求头仍有问题。
内容的提问来源于stack exchange,提问作者Corey Sutton
相关产品推荐
相关产品推荐

