React Native上传图片至Strapi后端遇Blob问题,网络请求失败
React Native 图片上传到Strapi(Cloudinary配置)报错解决
问题描述
在React Native应用中实现图片上传功能,Strapi后端已正确配置Cloudinary,通过Postman可正常发送请求上传图片,但React Native端处理Blob时始终返回**"TypeError: Network request failed"**错误,尝试过Axios、Buffer等方式均无效。
错误原因分析
- React Native环境中,
fetch处理base64转Blob存在兼容性问题,易引发网络请求失败 - 代码中未定义
setIsLoading对应的useState状态,执行时会报错 - 固定设置图片类型为
png,未适配实际选择的图片格式 - 不必要的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
相关产品推荐
相关产品推荐

