Flutter中如何获取iOS内部存储中的全部PDF文件?
Flutter iOS 无法列出所有PDF文件的解决方案
核心原因
iOS采用沙盒安全机制,应用默认只能访问自身沙盒目录,不允许直接遍历整个设备存储。你当前使用的getExternalStorageDirectory()在iOS上返回的是应用私有Documents目录,自然无法获取系统其他位置的PDF文件。
解决方案
1. 配置iOS权限
在Info.plist中添加以下权限描述(按需选择):
<!-- 访问下载目录权限 --> <key>NSDownloadsUsageDescription</key> <string>需要访问下载目录以查找PDF文件</string> <!-- 访问文件提供者目录(如iCloud、其他应用共享文件) --> <key>NSFileProviderDomainUsageDescription</key> <string>需要访问文件提供者目录以查找PDF文件</string>
2. 调整代码访问共享目录
修改getAllPdfFilesFromStorage方法,iOS端优先访问系统Downloads目录,同时扫描应用沙盒目录:
Future<List<Map<String, dynamic>>> getAllPdfFilesFromStorage() async { List<Map<String, dynamic>> pdfFiles = []; if (Platform.isAndroid) { // Android 可直接扫描根目录 final root = Directory('storage/emulated/0/'); await searchForPdfFiles(root, pdfFiles); } else { // iOS 仅能访问指定共享目录 + 应用沙盒 // 1. 扫描系统Downloads目录 final downloadsDir = await getDownloadsDirectory(); if (downloadsDir != null) { await searchForPdfFiles(downloadsDir, pdfFiles); } // 2. 扫描应用自身Documents目录 final appDocsDir = await getApplicationDocumentsDirectory(); await searchForPdfFiles(appDocsDir, pdfFiles); } return pdfFiles; } // 简化递归逻辑,直接使用listSync的recursive参数 Future<void> searchForPdfFiles(Directory dir, List<Map<String, dynamic>> pdfFiles) async { List<FileSystemEntity> entities = dir.listSync(recursive: true); for (FileSystemEntity entity in entities) { if (entity is File && entity.path.endsWith('.pdf')) { pdfFiles.add({ 'file': entity, 'name': entity.path.split('/').last, 'size': await entity.length(), }); } } }
3. 补充文件选择器功能(关键)
由于iOS禁止应用自动遍历全存储,若要获取设备上所有PDF,必须通过用户主动选择实现。使用file_picker包:
步骤:
- 添加依赖到
pubspec.yaml:
dependencies: file_picker: ^6.1.1
- 实现多文件选择功能:
Future<void> pickMultiplePdfFiles() async { final result = await FilePicker.platform.pickFiles( type: FileType.custom, allowedExtensions: ['pdf'], allowMultiple: true, ); if (result != null) { List<Map<String, dynamic>> pickedFiles = result.files.map((file) { final pdfFile = File(file.path!); return { 'file': pdfFile, 'name': file.name, 'size': file.size, }; }).toList(); // 合并已扫描文件与用户选择的文件 kDocController.localPdfFiles.value.addAll(pickedFiles); } }
重要说明
iOS的隐私安全规则决定了:
- 应用无法在后台自动扫描整个设备存储,仅能访问沙盒、指定共享目录(如Downloads)
- 要获取其他位置的文件,必须通过系统文件选择器让用户主动授权选择
内容的提问来源于stack exchange,提问作者Dhruvil Patel
相关产品推荐
相关产品推荐

