You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 14:37:32