uni.chooseFile在App端无法唤起系统文件管理器,Android需用ACTION_GET_CONTENT Intent,iOS需用UIDocumentPickerViewController;返回URI需解析为真实路径才能使用。

uni-app 在 App 端无法用 uni.chooseFile 唤起系统级文件管理器界面(如 Android 的“文件选择器”或 iOS 的“文件应用”),它在 App 平台实际调用的是相册/相机入口,不是通用文件浏览器。真要打开系统文件管理器,必须走原生层 —— Android 用 ACTION_GET_CONTENT 或 ACTION_OPEN_DOCUMENT,iOS 则受限于沙盒,只能通过 UIDocumentPickerViewController 选文件(且需权限+配置)。
Android 端唤起系统文件选择器(非相册)
App 端的 uni.chooseFile 在 Android 上默认打开的是媒体库(图片/视频),不是文件管理器。要选任意类型文件(如 PDF、TXT、CSV),必须调用原生 Intent。
- 需手动集成
plus.android,并在 manifest.json 中开启READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE(Android 10+ 建议同时开启requestLegacyExternalStorage) - 核心逻辑是创建
Intent.ACTION_GET_CONTENT,并设置intent.setType("*/*")或具体 MIME 类型(如"application/pdf") - 注意:返回的
uri是 content:// 协议,不能直接当文件路径用;必须用plus.android.resolveNativeUri(uri)(HBuilderX 3.9.12+)或自行解析 Document URI(KitKat+)才能拿到真实路径 - 示例关键片段:
const Intent = plus.android.importClass('android.content.Intent'); const intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType('*/*'); intent.addCategory(Intent.CATEGORY_OPENABLE); plus.android.runtimeMainActivity().startActivityForResult(intent, 1001);
iOS 端调用 UIDocumentPickerViewController
iOS 没有全局“文件管理器”可唤起,但可通过 UIDocumentPickerViewController 让用户从“文件”App 中选取文件 —— 这是最接近系统级文件选择的方式。
- 必须在
manifest.json → iOS 模块配置中添加NSDocumentPickerUsageDescription字符串(仅此一项,NSPhotoLibraryUsageDescription不够) - 权限不是运行时动态申请,而是首次调用时系统弹窗;若未配置描述,直接静默失败
- 支持模式:
import(复制进沙盒)、open(只读访问)、exportToService(分享到其他 App),推荐用import获取本地可读路径 - 返回路径是
file://开头的临时沙盒路径,需立即读取或拷贝,不可长期保存
为什么 uni.chooseFile 在 App 端不等于“打开文件管理器”
这个 API 在不同平台语义不一致:H5 调用的是 <input type="file">,微信小程序调用的是微信自己的文件选择面板,而 App 端(DCloud 引擎)底层映射为 plus.gallery.pick 或 plus.camera.capture,本质是媒体选择器。
- 即使传
type: 'all',Android 仍大概率跳转到“最近”或“图片”Tab,无法切换到“内部存储”“下载”等目录 - iOS 上会 fallback 到
uni.chooseImage行为,根本不会出现文件列表 - 官方文档未明确标注该限制,开发者常在真机测试阶段才发现“选不到 PDF”
替代方案:自建轻量文件浏览界面(推荐用于可控场景)
如果目标是让用户从“下载”“Documents”等固定目录选文件,比硬啃原生更稳的方式是:用 plus.io.requestFileSystem 列出指定路径下的文件,再渲染成列表。
- 路径建议用
plus.io.PUBLIC_DOCUMENTS(对应 iOS 的Documents/,Android 的/sdcard/Documents/),用户能感知、能管理 - 用
fileSystem.root.getDirectory+dir.createReader().readEntries递归读取,注意加 try/catch(权限缺失或路径不存在时会 fail) - 对每个
entry调用entry.file()获取lastModified、size等信息,比纯文件名更实用 - 缺点:无法跨分区(如 SD 卡根目录)、不支持网络位置、不能显示隐藏文件 —— 但已覆盖 80% 的导出/导入需求
真正麻烦的从来不是“怎么调”,而是“调了之后路径怎么用”。content:// URI 解析、Document Picker 的临时路径生命周期、PUBLIC vs PRIVATE 目录的清理策略 —— 这些细节没处理好,文件看似选到了,实际读不出内容或下次就找不着。别省这一步校验。


















