React Expo中如何利用Image Picker获取的Uri实现图片上传至服务器?
Hey there! I’ve gone through similar Android-to-Expo image upload workflows before, so let’s map your original Android Bitmap logic directly to Expo’s tooling to get the same result.
Your original Android flow was:
获取Bitmap → 缩放至500x500 → 压缩为JPEG(100%质量)→ 转Base64 → 上传至服务器
Here’s how to replicate this step-by-step in React Expo:
1. 安装必要依赖
First, install the Expo libraries we’ll need for image picking and manipulation:
npx expo install expo-image-picker expo-image-manipulator
2. 完整实现代码
Let’s break this into reusable functions that mirror your Android logic:
步骤1:获取图片Uri(你已经完成这部分,但这里是完整流程)
import * as ImagePicker from 'expo-image-picker'; import * as ImageManipulator from 'expo-image-manipulator'; const pickImage = async () => { // 请求相册权限 const permissionResult = await ImagePicker.requestMediaLibraryPermissionsAsync(); if (!permissionResult.granted) { alert("需要相册权限才能选择图片哦"); return; } // 从相册选择图片 const pickerResult = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, allowsEditing: false, quality: 1, // 先获取原图,后续我们自己处理压缩 }); if (!pickerResult.canceled) { // 拿到图片Uri后,开始处理并上传 await processAndUploadImage(pickerResult.assets[0].uri); } };
步骤2:缩放图片 + 生成Base64
This part directly replaces your Bitmap scaling and compression code:
const processAndUploadImage = async (imageUri) => { try { // 缩放图片到500x500,和你Android里的逻辑完全一致 const manipulatedImage = await ImageManipulator.manipulateAsync( imageUri, [{ resize: { width: 500, height: 500 } }], // 固定宽高缩放 { format: ImageManipulator.SaveFormat.JPEG, quality: 1, // 对应Android的100%压缩质量 base64: true, // 直接输出Base64字符串 } ); // 拿到编码后的图片字符串 const encodedImage = manipulatedImage.base64; // 上传到服务器 await uploadToServer(encodedImage); } catch (error) { console.error("图片处理失败:", error); alert("图片处理出错,请重试"); } };
步骤3:上传Base64到服务器
This sends the Base64 string to your server, just like your Android code did:
const uploadToServer = async (encodedImage) => { try { const response = await fetch("你的服务器上传接口地址", { method: "POST", headers: { "Content-Type": "application/json", // 按服务器要求调整Content-Type }, body: JSON.stringify({ image: encodedImage, // 字段名要和你Android端传给服务器的一致 }), }); if (!response.ok) { throw new Error(`服务器响应异常: ${response.status}`); } const result = await response.json(); console.log("上传成功!", result); alert("图片上传完成"); } catch (error) { console.error("上传失败:", error); alert("图片上传出错,请重试"); } };
可选:用FormData上传(更高效)
If your server supports multipart/form-data uploads, this is a better option than Base64 (since Base64 adds ~30% extra file size). Here’s how to adjust the upload step:
import { Platform } from 'react-native'; const uploadWithFormData = async (imageUri) => { // 先缩放图片(和之前一样) const manipulatedImage = await ImageManipulator.manipulateAsync( imageUri, [{ resize: { width: 500, height: 500 } }], { format: ImageManipulator.SaveFormat.JPEG, quality: 1 } ); // 构造FormData const formData = new FormData(); // 适配Android/iOS的Uri格式 const adjustedUri = Platform.OS === "android" ? manipulatedImage.uri : manipulatedImage.uri.replace("file://", ""); formData.append("image", { uri: adjustedUri, type: "image/jpeg", name: "uploaded_image.jpg", }); try { const response = await fetch("你的服务器上传接口地址", { method: "POST", headers: { "Content-Type": "multipart/form-data", }, body: formData, }); // 后续处理和之前一致 if (!response.ok) throw new Error(`服务器响应异常: ${response.status}`); const result = await response.json(); console.log("上传成功!", result); alert("图片上传完成"); } catch (error) { console.error("上传失败:", error); alert("图片上传出错,请重试"); } };
关键对应点
Bitmap.createScaledBitmap()→ImageManipulator.manipulateAsync()withresizeoptionbitmap.compress(JPEG, 100, baos)→ImageManipulatorwithformat: JPEGandquality: 1Base64.encodeToString()→ImageManipulatorwithbase64: true
内容的提问来源于stack exchange,提问作者E.Shahri

