使用file_picker从Google Drive选择视频无法显示的问题求助
问题:使用file_picker从Google Drive选择视频无法显示,本地存储正常
我在用file_picker插件直接从Google Drive选视频文件,但选中的视频没法显示;从手机本地存储选视频就正常工作。有人遇到过这个问题吗?
我的代码如下:
void _pickPerformanceVideo() async { _fileSelectionNotifier.performanceVideoFileLoaderNotifier(true); try { _performanceVideoPath = (await FilePicker.platform.pickFiles( allowedExtensions: ['mp4', 'mov'], type: FileType.custom, allowMultiple: false, onFileLoading: (FilePickerStatus status) => print(status), )) ?.files; await Future.delayed(Duration(seconds: 2)); if (_performanceVideoPath != null) { int sizeInBytes = _performanceVideoPath!.first.size; double sizeInMb = sizeInBytes / (1024 * 1024); if (sizeInMb <= 0) { _performanceVideoPath = null; final snackBar = showSnackBar(strVideoSizeError2, 3, duration: Duration(microseconds: 3000)); ScaffoldMessenger.of(context).showSnackBar(snackBar); } else if (sizeInMb > 250) { _performanceVideoPath = null; final snackBar = showSnackBar(strVideoSizeError, 3, duration: Duration(microseconds: 3000)); ScaffoldMessenger.of(context).showSnackBar(snackBar); } else { _fileSelectionNotifier.performanceFileNotifier(true); _fileSelectionNotifier .performanceFileNameNotifier(_performanceVideoPath!.first.name); _fileSelectionNotifier.setPerformanceValidationValue(false); } _fileSelectionNotifier.performanceVideoFileLoaderNotifier(false); } print(_performanceVideoPath!.single.path); } on PlatformException catch (e) { if (kDebugMode) { print('Unsupported operation' + e.toString()); } } catch (e) { if (kDebugMode) { print(e.toString()); } } finally { debugPrint("entered in finally block_performance vide"); _fileSelectionNotifier.performanceVideoFileLoaderNotifier(false); } }
原因分析
Google Drive这类云端存储的文件并没有本地文件系统的真实路径,file_picker返回的path字段会为空或无效,直接用这个路径加载视频自然失败。本地存储的文件因为有真实本地路径,所以能正常访问。
解决方案
不要依赖path字段,改用文件字节数据将云端文件复制到本地临时目录后再使用,具体修改如下:
1. 修改file_picker调用参数
开启withData: true,确保能获取到云端文件的字节数据:
final result = await FilePicker.platform.pickFiles( allowedExtensions: ['mp4', 'mov'], type: FileType.custom, allowMultiple: false, onFileLoading: (FilePickerStatus status) => print(status), withData: true, // 关键:开启后可获取云端文件字节 );
2. 处理空路径情况,复制文件到本地
如果path为空,就把字节数据写入本地临时文件,用临时路径加载视频:
// 处理云端文件:如果path为空,保存到本地临时目录 String? localPath; if (pickedFile.path == null && pickedFile.bytes != null) { // 创建临时文件 final tempDir = await getTemporaryDirectory(); final tempFile = File('${tempDir.path}/${pickedFile.name}'); await tempFile.writeAsBytes(pickedFile.bytes!); localPath = tempFile.path; } else { localPath = pickedFile.path; }
3. 完整修改后的代码
void _pickPerformanceVideo() async { _fileSelectionNotifier.performanceVideoFileLoaderNotifier(true); try { final result = await FilePicker.platform.pickFiles( allowedExtensions: ['mp4', 'mov'], type: FileType.custom, allowMultiple: false, onFileLoading: (FilePickerStatus status) => print(status), withData: true, ); if (result == null) { _fileSelectionNotifier.performanceVideoFileLoaderNotifier(false); return; } _performanceVideoPath = result.files; await Future.delayed(Duration(seconds: 2)); if (_performanceVideoPath != null) { final pickedFile = _performanceVideoPath!.first; int sizeInBytes = pickedFile.size; double sizeInMb = sizeInBytes / (1024 * 1024); if (sizeInBytes <= 0) { _performanceVideoPath = null; final snackBar = showSnackBar(strVideoSizeError2, 3, duration: Duration(seconds: 3)); // 修复时间单位错误 ScaffoldMessenger.of(context).showSnackBar(snackBar); } else if (sizeInMb > 250) { _performanceVideoPath = null; final snackBar = showSnackBar(strVideoSizeError, 3, duration: Duration(seconds: 3)); // 修复时间单位错误 ScaffoldMessenger.of(context).showSnackBar(snackBar); } else { // 处理云端文件:如果path为空,保存到本地临时目录 String? localPath; if (pickedFile.path == null && pickedFile.bytes != null) { final tempDir = await getTemporaryDirectory(); final tempFile = File('${tempDir.path}/${pickedFile.name}'); await tempFile.writeAsBytes(pickedFile.bytes!); localPath = tempFile.path; } else { localPath = pickedFile.path; } // 用localPath加载视频 _fileSelectionNotifier.performanceFileNotifier(true); _fileSelectionNotifier.performanceFileNameNotifier(pickedFile.name); _fileSelectionNotifier.setPerformanceValidationValue(false); print('本地路径:$localPath'); } _fileSelectionNotifier.performanceVideoFileLoaderNotifier(false); } } on PlatformException catch (e) { if (kDebugMode) { print('Unsupported operation: ${e.toString()}'); } _fileSelectionNotifier.performanceVideoFileLoaderNotifier(false); } catch (e) { if (kDebugMode) { print(e.toString()); } _fileSelectionNotifier.performanceVideoFileLoaderNotifier(false); } finally { debugPrint("entered in finally block_performance vide"); _fileSelectionNotifier.performanceVideoFileLoaderNotifier(false); } }
4. 添加依赖
需要path_provider来获取临时目录,在pubspec.yaml中添加:
dependencies: path_provider: ^2.1.1
内容的提问来源于stack exchange,提问作者viki
相关产品推荐
相关产品推荐

