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

如何通过fetch实现React Native(Expo)上传图片到Node.js服务器

图片上传失败问题修复方案

1. 图片选择模块逻辑修复

当前代码选图后仅存储了localUri字段,上传时调用的uri/title/type均为不存在的属性,导致FormData传入无效值,修正后代码如下:

function PickImage() {
  let [selectedImage, setSelectedImage] = useState(null);
  let openImagePickerAsync = async () => {
    let permissionResult = await ImagePicker.requestMediaLibraryPermissionsAsync();

    if (permissionResult.granted === false) {
      alert("需要获取相册访问权限!");
      return;
    }

    let pickerResult = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.Images, // 限制仅选图片,保证文件类型正确
    });
    if (pickerResult.cancelled === true) {
      return;
    }
    // 存储后续上传需要的所有字段
    setSelectedImage({
      uri: pickerResult.uri,
      // 从uri提取文件名,避免title字段不存在的问题
      name: pickerResult.uri.split('/').pop(),
      // 统一设置正确的文件类型,可根据实际图片格式调整
      type: 'image/jpeg'
    });
  };
  // 补充原代码缺失的组件返回逻辑
  return (
    <TouchableHighlight
      style={[
        styles.profileImgContainer,
        { borderColor: "#4632a1", borderWidth: 1 },
      ]}
      onPress={openImagePickerAsync}
    >
      <Image source={{ uri: selectedImage?.uri }} style={styles.thumbnail} />
    </TouchableHighlight>
  )
}

2. 上传请求逻辑修复

  • 禁止手动设置Content-Type: multipart/form-data请求头,FormData请求会自动生成带正确边界标识(boundary)的请求头,手动设置会丢失边界信息导致multer无法解析表单
  • 新增非空判断,避免未选图时发起无效请求
    修正后代码如下:
async function upload() {
  if(!selectedImage) {
    alert('请先选择图片');
    return;
  }
  const data = new FormData();
  data.append("image", {
    uri: selectedImage.uri,
    name: selectedImage.name,
    type: selectedImage.type,
  });

  const setting = {
    method: "POST",
    // 删除手动设置的Content-Type头,由环境自动生成
    body: data,
  };
  try {
    const fetchResponse = await fetch(url, setting);
    const resData = await fetchResponse.json();
    alert(JSON.stringify(resData));
  } catch (e) {
    alert(e);
  }
}

3. 服务端逻辑修复

  • 使用upload.single('image')配置后,上传的文件存储在req.file对象中,req.body仅存放普通表单字段,原代码取req.body.image必然为空
  • 需确认multer初始化时已经配置了正确的存储路径,否则文件不会存入本地文件夹

multer初始化参考配置

const multer = require('multer');
// 配置磁盘存储路径和文件名规则
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './uploads') // 需提前在项目根目录创建uploads文件夹
  },
  filename: function (req, file, cb) {
    cb(null, Date.now() + '-' + file.originalname)
  }
})
const upload = multer({ storage: storage })

接口修正代码

app.post("/users", upload.single("image"), async (req, res) => {
  console.log('上传的文件信息:', req.file); // 文件信息存在req.file中
  console.log('普通表单字段:', req.body);
  const img = req.file;
  if (!img) {
    console.log("no image");
    return res.status(400).send({ error: "未获取到上传的图片" });
  }
  res.send({ congrats: "data recieved", fileInfo: img });
});

内容的提问来源于stack exchange,提问作者zeeshan zamurd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 06:27:02