uni-app app端无法直接用uni.choosefile选任意文件,需原生调用:android用action_get_content配合uri解析,ios用uidocumentpickerviewcontroller并配置权限描述;读取时须用plus.io或getfilesystemmanager,禁用uni.readfile。

uni-app 在 App 端无法用 uni.chooseFile 或 uni.chooseMessageFile 唤起真正的系统文件管理器(如 Android 的“文件选择器”或 iOS 的“文件”App),它默认只打开相册/相机;要选 PDF、TXT、CSV 等任意类型文件,必须走原生层调用。
Android 端用 ACTION_GET_CONTENT 启动系统文件选择器
Android 上不能依赖 uni.chooseFile,得用 plus.android 调原生 Intent。关键不是“打开什么”,而是“怎么拿到可用路径”——返回的 content:// URI 必须解析,否则后续读取会失败。
-
Intent.ACTION_GET_CONTENT是最兼容的选择,比ACTION_OPEN_DOCUMENT更容易适配老版本系统 - 务必设置
intent.addCategory(Intent.CATEGORY_OPENABLE),否则部分厂商 ROM(如华为 EMUI)可能不显示文件项 -
intent.setType("*/*")支持所有类型,但若限定范围(如 PDF),应写"application/pdf",不要用".pdf"(MIME 类型错误会导致白屏) - 返回的
data.getData()是content://URI,不能直接当文件路径用;HBuilderX 3.9.12+ 可用plus.android.resolveNativeUri(uri)解析,旧版需手动通过ContentResolver查询_data字段(KitKat+ 有兼容性坑) - Android 10+ 需在
manifest.json中开启requestLegacyExternalStorage,否则部分设备解析出的路径为空
iOS 端只能用 UIDocumentPickerViewController
iOS 没有全局文件管理器,UIDocumentPickerViewController 是唯一合法方式,但它不等于“打开文件 App”,而是弹出一个系统级选择浮层,用户可从“iCloud 云盘”“On My iPhone”等位置选文件。
- 必须在
manifest.json → iOS → 权限配置中添加NSDocumentPickerUsageDescription字符串,仅此一项有效;NSPhotoLibraryUsageDescription不管用 - 首次调用时系统弹窗申请权限,若未配置描述文案,调用静默失败,控制台无报错,也无回调
- 返回的是临时复制路径(
file://),可直接用于uni.getFileSystemManager().readFile,但注意:iOS 14+ 对某些路径(如 iCloud 同步中文件)可能返回nil,需加空值判断 - 不能设置 MIME 类型过滤(如只让选 PDF),iOS 层面不支持;只能靠前端对
res.type或后缀做二次校验
App 端读取选中文件内容的正确方式
拿到路径后别用 uni.readFile —— 它只认 tempFilePath(上传/下载生成的路径),对原生返回的真实路径会报 no permission 或返回空内容。
- 优先用
uni.getFileSystemManager()的readFile方法,它在 App 平台能绕过部分沙盒限制 - 更稳妥的是用
plus.io.resolveLocalFileSystemURL(path)+fileEntry.file()获取Blob,再转成 ArrayBuffer 或 base64(尤其适合传给后端二进制接口) - 读取大文件(>5MB)时,
readFile可能卡 UI,建议切到子线程(Android 用HandlerThread,iOS 用dispatch_queue_t)——原生插件里才可控,JS 层只能分块读 - 注意:iOS 返回路径可能含中文或空格,需
encodeURI处理后再传给readFile,否则报错Failed to execute 'readAsText' on 'FileReader'
真正难的不是“调起界面”,而是处理不同 Android 厂商 ROM 对 content:// URI 的解析差异,以及 iOS 文件生命周期(比如用户删了源文件,临时路径就失效)。这些细节不写死在原生层,光靠 JS 补丁很难兜住。











