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

React Native上传图片至Strapi后端遇Blob问题,网络请求失败

React Native 图片上传到Strapi(Cloudinary配置)报错解决

问题描述

在React Native应用中实现图片上传功能,Strapi后端已正确配置Cloudinary,通过Postman可正常发送请求上传图片,但React Native端处理Blob时始终返回**"TypeError: Network request failed"**错误,尝试过Axios、Buffer等方式均无效。

错误原因分析

  1. React Native环境中,fetch处理base64转Blob存在兼容性问题,易引发网络请求失败
  2. 代码中未定义setIsLoading对应的useState状态,执行时会报错
  3. 固定设置图片类型为png,未适配实际选择的图片格式
  4. 不必要的base64转Blob步骤增加了出错概率

修复后的完整代码

import React, { useState } from 'react';
import { Button, Image, StyleSheet, View } from 'react-native';
import * as ImagePicker from 'expo-image-picker';
import { useAuth } from '../../../hooks';

export default function UploadScreen() {
  const [image, setImage] = useState(null);
  const [isLoading, setIsLoading] = useState(false); // 补全缺失的状态定义
  const { user, updateUser } = useAuth();

  const pickImage = async () => {
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.All,
      allowsEditing: true,
      aspect: [4, 3],
      quality: 1,
      // 无需开启base64,直接使用uri即可
    });

    if (!result.canceled) {
      try {
        setIsLoading(true);
        const selectedAsset = result.assets[0];
        
        // 直接使用图片uri构造FormData,避免base64转Blob
        const formData = new FormData();
        formData.append('files', {
          uri: selectedAsset.uri,
          name: `avatar.${selectedAsset.type.split('/')[1]}`, // 根据实际类型设置文件名
          type: selectedAsset.type, // 图片的MIME类型
        });
        formData.append('ref', 'user'); // 关联的模型名称
        formData.append('refId', user.id); // 用户ID
        formData.append('field', 'avatar_url'); // 模型中对应的字段名

        const response = await fetch('http://10.6.7.55:1337/api/upload', {
          method: 'POST',
          body: formData,
          // React Native会自动处理FormData的Content-Type,无需手动设置
        });

        if (response.ok) {
          const responseData = await response.json();
          const updatedUser = { ...user, avatar_url: responseData[0]?.url };
          updateUser(updatedUser);
          setImage(responseData[0]?.url); // 更新本地图片状态
        } else {
          console.error('图片上传到Strapi失败');
          const errorText = await response.text();
          console.error('错误详情:', errorText); // 打印详细错误信息
        }
      } catch (error) {
        console.error('图片上传过程出错:', error);
      } finally {
        setIsLoading(false);
      }
    }
  };

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Button 
        title={isLoading ? '上传中...' : '从相册选择图片'} 
        onPress={pickImage} 
        disabled={isLoading}
      />
      {image && (
        <Image 
          source={{ uri: image }}
          style={{ width: '100%', height: 110, borderTopLeftRadius: 10, borderTopRightRadius: 10, marginTop: 20 }} 
        />
      )}
      {user?.avatar_url && (
        <Image 
          source={{ uri: user.avatar_url }} 
          style={styles.avatar} 
        />
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  avatar: {
    width: 80,
    height: 80,
    borderRadius: 40,
    marginTop: 20,
  },
});

关键修复点说明

  • 移除base64转Blob流程:直接使用ImagePicker返回的本地uri构造FormData,这是React Native中文件上传的标准做法,避免了Blob转换的兼容性问题
  • 补全状态定义:添加isLoading对应的useState,避免未定义变量报错
  • 动态设置文件类型:根据选择图片的实际MIME类型设置文件名和类型,适配不同格式的图片
  • 增强错误排查:添加响应错误详情打印,方便定位Strapi返回的具体问题
  • 优化交互:上传过程中禁用按钮并修改标题,提升用户体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 16:28:13