flutter_file_picker/lib/src/file_picker_io.dart

122 lines
3.7 KiB
Dart

import 'dart:async';
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:file_picker/src/platform_file.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
final MethodChannel _channel = MethodChannel(
'miguelruivo.flutter.plugins.filepicker',
Platform.isLinux || Platform.isWindows || Platform.isMacOS
? const JSONMethodCodec()
: const StandardMethodCodec(),
);
const EventChannel _eventChannel =
EventChannel('miguelruivo.flutter.plugins.filepickerevent');
/// An implementation of [FilePicker] that uses method channels.
class FilePickerIO extends FilePicker {
static const String _tag = 'MethodChannelFilePicker';
static StreamSubscription? _eventSubscription;
@override
Future<FilePickerResult?> pickFiles({
FileType type = FileType.any,
List<String>? allowedExtensions,
String? dialogTitle,
Function(FilePickerStatus)? onFileLoading,
bool? allowCompression = true,
bool allowMultiple = false,
bool? withData = false,
bool? withReadStream = false,
}) =>
_getPath(
type,
allowMultiple,
allowCompression,
allowedExtensions,
onFileLoading,
withData,
withReadStream,
);
@override
Future<bool?> clearTemporaryFiles() async =>
_channel.invokeMethod<bool>('clear');
@override
Future<String?> getDirectoryPath({String? dialogTitle}) async {
try {
return await _channel.invokeMethod('dir', {});
} on PlatformException catch (ex) {
if (ex.code == "unknown_path") {
print(
'[$_tag] Could not resolve directory path. Maybe it\'s a protected one or unsupported (such as Downloads folder). If you are on Android, make sure that you are on SDK 21 or above.');
}
}
return null;
}
Future<FilePickerResult?> _getPath(
FileType fileType,
bool allowMultipleSelection,
bool? allowCompression,
List<String>? allowedExtensions,
Function(FilePickerStatus)? onFileLoading,
bool? withData,
bool? withReadStream,
) async {
final String type = describeEnum(fileType);
if (type != 'custom' && (allowedExtensions?.isNotEmpty ?? false)) {
throw Exception(
'You are setting a type [$fileType]. Custom extension filters are only allowed with FileType.custom, please change it or remove filters.');
}
try {
_eventSubscription?.cancel();
if (onFileLoading != null) {
_eventSubscription = _eventChannel.receiveBroadcastStream().listen(
(data) => onFileLoading((data as bool)
? FilePickerStatus.picking
: FilePickerStatus.done),
onError: (error) => throw Exception(error),
);
}
final List<Map>? result = await _channel.invokeListMethod(type, {
'allowMultipleSelection': allowMultipleSelection,
'allowedExtensions': allowedExtensions,
'allowCompression': allowCompression,
'withData': withData,
});
if (result == null) {
return null;
}
final List<PlatformFile> platformFiles = <PlatformFile>[];
for (final Map platformFileMap in result) {
platformFiles.add(
PlatformFile.fromMap(
platformFileMap,
readStream: withReadStream!
? File(platformFileMap['path']).openRead()
: null,
),
);
}
return FilePickerResult(platformFiles);
} on PlatformException catch (e) {
print('[$_tag] Platform exception: $e');
rethrow;
} catch (e) {
print(
'[$_tag] Unsupported operation. Method not found. The exception thrown was: $e');
rethrow;
}
}
}