react-native-document-picker调用返回uri为undefined如何解决
问题根因
你代码里拿不到uri有三个核心错误:
DocumentPicker.pick()是异步Promise接口,你没有加await等待异步返回,直接访问返回值的uri属性,此时拿到的是未完成的Promise对象,自然不存在uri字段。- v3及以上版本的
react-native-document-picker,pick方法默认返回选中文件的数组结构,哪怕只选单个文件,也需要取下标拿到具体文件对象,直接对返回数组取uri同样会得到undefined。 - 额外注意:Android平台默认返回的是
content://协议的临时共享uri,不是文件系统的绝对路径,直接传给PDF打开库大概率会报路径无权限/找不到文件,需要做路径转换。
修复步骤
- 给
openFile方法加async声明,调用pick时加await等待结果返回,同时增加try/catch捕获用户取消选择的异常。 - 从返回的文件数组中取出第一个文件对象,再读取uri属性。
- 针对Android平台的content类型uri,用
rn-fetch-blob的stat接口转换为真实的文件系统绝对路径;iOS平台返回的路径按需补全file://前缀适配PDF打开组件的要求。 - 补全两端的必要权限配置,避免路径访问被系统拦截。
修复后完整代码
import { StyleSheet, Text, View, Button, Platform } from 'react-native' import React from 'react' import DocumentPicker from 'react-native-document-picker' import RNFetchBlob from 'rn-fetch-blob' import Pdf from 'react-native-open-pdf'; const openPdfex = () => { const openFile = async () => { try { // 等待文件选择结果返回,copyTo配置可直接生成应用缓存目录下的可访问文件副本,规避权限问题 const fileList = await DocumentPicker.pick({ type: [DocumentPicker.types.allFiles], copyTo: 'cachesDirectory' }); const selectedFile = fileList[0]; let filePath = selectedFile.uri; // 安卓平台转换content协议uri为真实绝对路径 if (Platform.OS === 'android' && filePath.startsWith('content://')) { const fileStat = await RNFetchBlob.fs.stat(filePath); filePath = fileStat.path; } // iOS平台补全file协议前缀 if (Platform.OS === 'ios' && !filePath.startsWith('file://')) { filePath = `file://${filePath}`; } console.log("absolute path =====> ", filePath); // 拿到路径后直接调用PDF打开方法即可 // Pdf.open(filePath); } catch (err) { // 用户主动取消选择不属于错误,单独处理 if (DocumentPicker.isCancel(err)) { console.log('用户取消文件选择'); return; } console.error('文件选择流程出错:', err); } } return ( <View> <Text>openPdf</Text> <Button title='Open PDF' onPress={openFile}></Button> </View> ) } export default openPdfex;
必要权限配置
Android端
在android/app/src/main/AndroidManifest.xml的<manifest>标签内添加以下权限,适配不同Android版本的存储访问规则:
<!-- Android12及以下读存储权限 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <!-- Android13及以上细分媒体权限 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
iOS端
在ios/[你的项目名]/Info.plist中添加文档访问权限描述:
<key>NSDocumentsFolderUsageDescription</key> <string>需要访问文档内容以打开PDF文件</string>
内容的提问来源于stack exchange,提问作者user18749224
相关产品推荐
相关产品推荐

