2018-06-23 01:22:04 +00:00
import ' dart:async ' ;
2019-03-12 01:25:23 +00:00
import ' dart:io ' ;
2018-06-23 01:22:04 +00:00
2020-04-27 21:25:57 +00:00
import ' package:flutter/foundation.dart ' ;
2018-06-23 01:22:04 +00:00
import ' package:flutter/services.dart ' ;
2018-11-30 16:15:09 +00:00
2019-03-12 01:25:23 +00:00
enum FileType {
2020-03-14 17:32:05 +00:00
any ,
2020-04-27 21:25:57 +00:00
media ,
2020-03-14 17:32:05 +00:00
image ,
video ,
audio ,
custom ,
2019-03-12 01:25:23 +00:00
}
2018-06-23 01:22:04 +00:00
class FilePicker {
2019-03-08 01:42:07 +00:00
FilePicker . _ ( ) ;
2020-06-04 21:49:39 +00:00
static const MethodChannel _channel = const MethodChannel ( ' miguelruivo.flutter.plugins.filepicker ' ) ;
2020-03-14 17:32:05 +00:00
static const String _tag = ' FilePicker ' ;
2019-03-08 01:42:07 +00:00
2019-03-12 01:25:23 +00:00
/// Returns an iterable `Map<String,String>` where the `key` is the name of the file
/// and the `value` the path.
///
2020-04-05 16:01:31 +00:00
/// A `List` with [allowedExtensions] can be provided to filter the allowed files to picked.
/// If provided, make sure you select `FileType.custom` as type.
/// Defaults to `FileType.any`, which allows any combination of files to be multi selected at once.
2020-06-04 21:49:39 +00:00
static Future < Map < String , String > > getMultiFilePath ( { FileType type = FileType . any , List < String > allowedExtensions } ) async = >
2020-04-27 21:25:57 +00:00
await _getPath ( describeEnum ( type ) , true , allowedExtensions ) ;
2019-03-12 01:25:23 +00:00
/// Returns an absolute file path from the calling platform.
///
2020-04-05 16:01:31 +00:00
/// Extension filters are allowed with `FileType.custom`, when used, make sure to provide a `List`
/// of [allowedExtensions] (e.g. [`pdf`, `svg`, `jpg`].).
/// Defaults to `FileType.any` which will display all file types.
2020-06-04 21:49:39 +00:00
static Future < String > getFilePath ( { FileType type = FileType . any , List < String > allowedExtensions } ) async = >
2020-04-27 21:25:57 +00:00
await _getPath ( describeEnum ( type ) , false , allowedExtensions ) ;
2019-03-12 01:25:23 +00:00
/// Returns a `File` object from the selected file path.
///
/// This is an utility method that does the same of `getFilePath()` but saving some boilerplate if
/// you are planing to create a `File` for the returned path.
2020-06-04 21:49:39 +00:00
static Future < File > getFile ( { FileType type = FileType . any , List < String > allowedExtensions } ) async {
final String filePath = await _getPath ( describeEnum ( type ) , false , allowedExtensions ) ;
2019-03-16 12:18:10 +00:00
return filePath ! = null ? File ( filePath ) : null ;
2019-03-12 01:25:23 +00:00
}
2020-05-01 16:49:35 +00:00
/// Asks the underlying platform to remove any temporary files created by this plugin.
///
/// This typically relates to cached files that are stored in the cache directory of
/// each platform and it isn't required to invoke this as the system should take care
/// of it whenever needed. However, this will force the cleanup if you want to manage those on your own.
///
/// Returns `true` if the files were removed with success, `false` otherwise.
static Future < bool > clearTemporaryFiles ( ) async {
return _channel . invokeMethod ( ' clear ' ) ;
}
2019-08-31 14:14:28 +00:00
/// Returns a `List<File>` object from the selected files paths.
///
/// This is an utility method that does the same of `getMultiFilePath()` but saving some boilerplate if
/// you are planing to create a list of `File`s for the returned paths.
2020-06-04 21:49:39 +00:00
static Future < List < File > > getMultiFile ( { FileType type = FileType . any , List < String > allowedExtensions } ) async {
final Map < String , String > paths = await _getPath ( describeEnum ( type ) , true , allowedExtensions ) ;
return paths ! = null & & paths . isNotEmpty ? paths . values . map ( ( path ) = > File ( path ) ) . toList ( ) : null ;
2019-08-31 14:14:28 +00:00
}
2020-06-04 21:49:39 +00:00
/// Selects a directory and returns its absolute path.
///
/// On Android, this requires to be running on SDK 21 or above, else won't work.
/// Returns `null` if folder path couldn't be resolved.
static Future < String > getDirectoryPath ( ) 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 ;
}
}
static Future < dynamic > _getPath ( String type , bool allowMultipleSelection , List < String > allowedExtensions ) async {
2020-04-28 09:30:59 +00:00
if ( type ! = ' custom ' & & ( allowedExtensions ? . isNotEmpty ? ? false ) ) {
2020-06-04 21:49:39 +00:00
throw Exception ( ' If you are using a custom extension filter, please use the FileType.custom instead. ' ) ;
2020-04-05 16:01:31 +00:00
}
2018-12-27 14:02:24 +00:00
try {
2020-04-05 16:01:31 +00:00
dynamic result = await _channel . invokeMethod ( type , {
' allowMultipleSelection ' : allowMultipleSelection ,
' allowedExtensions ' : allowedExtensions ,
} ) ;
if ( result ! = null & & allowMultipleSelection ) {
2019-03-06 01:16:35 +00:00
if ( result is String ) {
result = [ result ] ;
}
2020-06-04 21:49:39 +00:00
return Map < String , String > . fromIterable ( result , key: ( path ) = > path . split ( ' / ' ) . last , value: ( path ) = > path ) ;
2019-03-06 01:16:35 +00:00
}
return result ;
2018-12-27 14:02:24 +00:00
} on PlatformException catch ( e ) {
2019-06-24 10:10:19 +00:00
print ( ' [ $ _tag ] Platform exception: $ e ' ) ;
rethrow ;
2018-12-27 14:02:24 +00:00
} catch ( e ) {
2020-06-04 21:49:39 +00:00
print ( ' [ $ _tag ] Unsupported operation. Method not found. The exception thrown was: $ e ' ) ;
2019-06-24 10:10:19 +00:00
rethrow ;
2019-03-11 00:01:44 +00:00
}
}
2018-09-11 14:59:35 +00:00
}