React Native中如何选取Excel文件并通过API上传?
解决React Native中content:// URI无法上传Excel文件的问题
Android返回的content://类型URI是系统内容提供者的统一标识符,并非真实文件路径,无法直接被多数上传API识别。以下是两种可行的解决方案:
方案1:将content URI转换为真实文件路径(使用react-native-fs)
- 先安装依赖包:
npm install react-native-fs --save # 或使用yarn yarn add react-native-fs
- 编写URI转换函数,获取可用于上传的文件路径或Base64内容:
import RNFS from 'react-native-fs'; import { Platform } from 'react-native'; async function getValidFileResource(contentUri) { try { if (Platform.OS === 'android') { // 直接读取文件为Base64(适合小文件,无需路径转换) const base64Content = await RNFS.readFile(contentUri, 'base64'); // 或尝试获取真实文件路径(部分场景适用) const statResult = await RNFS.stat(contentUri); return statResult.path || base64Content; } // iOS下直接返回原URI即可 return contentUri; } catch (error) { console.error('URI转换失败:', error); return null; } }
- 结合文件选择与上传逻辑:
import DocumentPicker from 'react-native-document-picker'; async function pickAndUploadExcel() { try { // 选取Excel文件 const pickResult = await DocumentPicker.pick({ type: [DocumentPicker.types.excel], }); // 转换URI为可用资源 const fileResource = await getValidFileResource(pickResult.uri); if (!fileResource) return; // 构建FormData用于上传 const formData = new FormData(); formData.append('excel_file', { uri: Platform.OS === 'android' ? `file://${fileResource}` : fileResource, name: pickResult.name, type: pickResult.type, }); // 调用上传API const uploadResponse = await fetch('你的上传API地址', { method: 'POST', body: formData, headers: { 'Content-Type': 'multipart/form-data', }, }); const responseData = await uploadResponse.json(); console.log('上传成功:', responseData); } catch (err) { if (DocumentPicker.isCancel(err)) { console.log('用户取消文件选择'); } else { console.error('文件选择或上传失败:', err); } } }
方案2:直接获取文件Blob(react-native-document-picker v6+版本支持)
如果使用的是v6及以上版本的react-native-document-picker,可以直接通过getFile()方法获取Blob对象,跳过URI转换步骤:
import DocumentPicker from 'react-native-document-picker'; async function pickAndUploadExcel() { try { const pickResult = await DocumentPicker.pick({ type: [DocumentPicker.types.excel], }); // 获取文件Blob const fileBlob = await pickResult.getFile(); const formData = new FormData(); formData.append('excel_file', fileBlob, pickResult.name); // 上传逻辑 const uploadResponse = await fetch('你的上传API地址', { method: 'POST', body: formData, headers: { 'Content-Type': 'multipart/form-data', }, }); const responseData = await uploadResponse.json(); console.log('上传成功:', responseData); } catch (err) { if (DocumentPicker.isCancel(err)) { console.log('用户取消文件选择'); } else { console.error('操作失败:', err); } } }
注意事项
- Android权限配置:在
AndroidManifest.xml中添加必要权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android 10-12 可选MANAGE_EXTERNAL_STORAGE权限 --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <!-- Android 13+ 需要单独请求媒体权限 --> <uses-permission android:name="android.permission.READ_MEDIA_DOCUMENTS" />
- Android 13+需动态申请权限:
import { PermissionsAndroid } from 'react-native'; async function requestFilePermission() { if (Platform.OS === 'android') { const granted = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.READ_MEDIA_DOCUMENTS, { title: '文件读取权限申请', message: '需要读取设备中的Excel文件以完成上传', buttonPositive: '允许', buttonNegative: '取消', }, ); return granted === PermissionsAndroid.RESULTS.GRANTED; } return true; }
内容的提问来源于stack exchange,提问作者Abdul Rehman
相关产品推荐
相关产品推荐

