Flutter使用image_picker/file_picker获取图片/视频原始路径以删除原文件
Flutter 导入相册资源后删除原文件解决方案
该问题本质是系统权限限制导致的:从Android 10、iOS 11开始,系统不再向普通第三方应用直接暴露相册原始文件的真实路径,
image_picker、file_picker这类通用选择器的实现逻辑是读取相册原始文件生成一份缓存副本返回给应用,你拿到的路径都是副本的缓存路径,自然无法操作原始文件。
要实现需求需要使用能直接操作相册原始资源的工具类库,推荐使用photo_manager,具体实现步骤如下:
1. 权限配置
- Android端:在
android/app/src/main/AndroidManifest.xml中添加权限声明- Android 13及以上:添加
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />、<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> - Android 12及以下:添加
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />、<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- Android 13及以上:添加
- iOS端:在
ios/Runner/Info.plist中添加相册权限声明,key为NSPhotoLibraryUsageDescription,value填写你需要向用户说明的权限用途文案。
2. 核心逻辑实现
核心流程为:请求相册权限→展示相册资源供用户选择→导出选中资源到应用目标存储路径→删除相册内原始资源,参考代码如下:
import 'package:photo_manager/photo_manager.dart'; import 'package:path_provider/path_provider.dart'; Future<void> pickAndDeleteOriginalAsset() async { // 第一步:请求相册读写权限 final PermissionState permissionState = await PhotoManager.requestPermissionExtend(); if (!permissionState.isAuth) { // 权限未通过,自行处理异常逻辑 return; } // 第二步:获取相册列表,可自行实现相册选择UI final List<AssetPathEntity> albumList = await PhotoManager.getAssetPathList( type: RequestType.common, // 同时支持图片+视频,可修改为RequestType.image/RequestType.video筛选类型 ); // 第三步:获取选中相册内的资源列表,可自行实现资源选择UI,此处取第一个相册的资源做示例 final List<AssetEntity> assetList = await albumList[0].getAssetListPaged(page: 0, size: 200); // 第四步:假设用户选中了列表中第一个资源,先导出资源文件到应用私有目录 final AssetEntity selectedAsset = assetList[0]; final File? originFile = await selectedAsset.file; if (originFile == null) return; // 自定义目标存储路径,此处用应用文档目录做示例 final String targetDir = (await getApplicationDocumentsDirectory()).path; final String targetPath = '$targetDir/${DateTime.now().millisecondsSinceEpoch}.${selectedAsset.mimeType?.split('/').last ?? 'jpg'}'; await originFile.copy(targetPath); // 到这里资源已经成功导入到你的应用目录下 // 第五步:删除相册内的原始资源 final bool deleteResult = await PhotoManager.editor.deleteWithIds([selectedAsset.id]); if (deleteResult) { // 原始资源删除成功逻辑 } else { // 原始资源删除失败逻辑,通常是权限不足或者系统拦截 } }
注意事项
- 部分国产Android系统、iOS系统删除相册资源时会弹出系统级确认弹窗,需要用户手动确认后才能删除,属于系统限制无法绕过
- iOS如果用户只授予了有限相册访问权限,你只能删除用户授权给应用访问的那部分资源
- 请确保你删除用户相册资源的操作已获得用户明确同意,否则可能导致应用被应用商店下架
内容的提问来源于stack exchange,提问作者Sameer khan
相关产品推荐
相关产品推荐

