Expo 49下React Native移动端及Web端Cloudinary视频上传问题求解
问题分析与解决方案
核心问题
- 移动端返回undefined:你错误地对Expo ImagePicker返回的本地文件URI执行
split(',')[1]操作——移动端的URI是file://开头的本地路径,并非base64格式,split后会得到undefined,导致上传的文件无效。 - Web端Bad Request:Web端返回的URI是带
data:video/mp4;base64,前缀的完整base64字符串,你去掉前缀后,Cloudinary无法识别文件格式,从而返回400错误。 - FormData构造错误:跨平台上传视频时,移动端和Web端需要不同的文件格式处理逻辑,你当前的传参方式不兼容两端。
修正后的代码
1. 视频选择函数 pickVideo
const pickVideo = async () => { try { const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Videos, allowsEditing: true, quality: 1, }); if (!result.canceled) { const asset = result.assets[0]; // 直接使用原始URI,不做split操作 const uri = await postToCloundinaryVideo(asset); console.log('上传完成,返回URL:', uri); } } catch (err) { console.error('视频选择或上传失败:', err); } };
2. Cloudinary上传函数 postToCloundinaryVideo
import { Platform } from 'react-native'; const postToCloundinaryVideo = async (asset) => { const formData = new FormData(); let file; // 区分平台处理文件 if (Platform.OS === 'web') { // Web端:将base64 URI转为Blob(标准上传方式) const blob = await fetch(asset.uri).then(res => res.blob()); file = blob; } else { // 移动端:构造符合FormData要求的文件对象 file = { uri: asset.uri, name: `video_${Date.now()}.mp4`, type: asset.mimeType || 'video/mp4', }; } formData.append('file', file); formData.append('upload_preset', 'my_value'); formData.append('cloud_name', 'my_cloud_name'); const response = await fetch(`https://api.cloudinary.com/v1_1/my_cloud_name/video/upload`, { method: 'POST', body: formData, // 不要手动设置Content-Type,浏览器/Expo会自动生成正确的multipart/form-data头 }); const data = await response.json(); if (!response.ok) { throw new Error(data.error?.message || '上传失败'); } return data.url; };
额外注意事项
- 确认你的Cloudinary上传预设(
upload_preset)为未签名状态,且允许上传视频类型。 - 移动端测试时,确保应用已获取媒体文件读取权限(Expo ImagePicker会自动请求,也可在
app.json中显式声明权限)。 - Web端若不想转Blob,也可直接传入完整的base64 URI(即
asset.uri),Cloudinary同样支持该方式。
内容的提问来源于stack exchange,提问作者Charlie_57
相关产品推荐
相关产品推荐

