An external package can be used to enable reading files from an Android or iOS device
file_picker
package allows to use a native file explorer to pick single or multiple absolute file paths, with filtering support
Single file
File file = await FilePicker.getFile();
It accepts two optional parameters: fileType
and allowedExtensions
to filter selectable files
Multiple files
List<File> files = await FilePicker.getMultiFile();
Multiple files with extension filter
List<File> files = await FilePicker.getMultiFile(
type: FileType.custom,
allowedExtensions: ['jpg', 'pdf', 'doc'],
);
Available fileTypes:
FileType.any
- to pick all available files FileType.custom
- to pick files based on allowedExtensions
provided FileType.image
- to pick a single image file; opens gallery on iOS FileType.video
- to pick a single video file; opens gallery on iOS FileType.audio
- to pick a single audio file; opens music on iOS DRM protected files returns null
instead of path
Single file path
String path = await FilePicker.getFilePath()
filePath = await FilePicker.getFilePath(type: FileType.image);
Multiple paths
// Multi file path
Map<String,String> filesPaths; = await FilePicker.getMultiFilePath(); // to pick multiple files of any format
filePaths = await FilePicker.getMultiFilePath(type: FileType.image); // to pick multiple image files
List<String> allNames = filePaths.keys; // List of file names
List<String> allPaths = filePaths.values; // List of paths
Check Flutter installation to setup Flutter
Use flutter create
command to create a Flutter project (here file_picker_app :
flutter create file_picker_app
Add file_picker
package to pubspec.yaml
dependencies:
file_picker: "^1.12.0"
flutter:
sdk: flutter
Run following command to add dependency
flutter pub get
Find and open file_picker_app (project directory) → android → app → src → main → AndroidManifest.xml
Add READ_EXTERNAL_STORAGE
permission (before <application tag)
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.file_picker_app">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
In iOS 11, user is prompted for permission when accessing photos
Files can be picked from iCloud without explicitly configuring Info.plist
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:file_picker/file_picker.dart';
void main() => runApp(FilePickerApp());
class FilePickerApp extends StatefulWidget {
@override
FilePickerAppState createState() => new FilePickerAppState();
}
class FilePickerAppState extends State<FilePickerApp> {
String fileName;
String path;
Map<String, String> paths;
List<String> extensions;
bool isLoadingPath = false;
bool isMultiPick = false;
FileType fileType;
void _openFileExplorer() async {
setState(() => isLoadingPath = true);
try {
if (isMultiPick) {
path = null;
paths = await FilePicker.getMultiFilePath(type: fileType? fileType: FileType.any, allowedExtensions: extensions);
}
else {
path = await FilePicker.getFilePath(type: fileType? fileType: FileType.any, allowedExtensions: extensions);
paths = null;
}
}
on PlatformException catch (e) {
print("Unsupported operation" + e.toString());
}
if (!mounted) return;
setState(() {
isLoadingPath = false;
fileName = path != null ? path.split('/').last : paths != null
? paths.keys.toString() : '...';
});
}
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: const Text('File Picker example app'),
),
body: new Center(
child: new Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
child: new SingleChildScrollView(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Padding(
padding: const EdgeInsets.only(top: 20.0),
child: new DropdownButton(
hint: new Text('Select file type'),
value: fileType,
items: <DropdownMenuItem>[
new DropdownMenuItem(
child: new Text('Audio'),
value: FileType.audio,
),
new DropdownMenuItem(
child: new Text('Image'),
value: FileType.image,
),
new DropdownMenuItem(
child: new Text('Video'),
value: FileType.video,
),
new DropdownMenuItem(
child: new Text('Any'),
value: FileType.any,
),
],
onChanged: (value) => setState(() {
fileType = value;
})
),
),
new ConstrainedBox(
constraints: BoxConstraints.tightFor(width: 200.0),
child: new SwitchListTile.adaptive(
title: new Text('Pick multiple files', textAlign: TextAlign.right),
onChanged: (bool value) => setState(() => isMultiPick = value),
value: isMultiPick,
),
),
new Padding(
padding: const EdgeInsets.only(top: 50.0, bottom: 20.0),
child: new RaisedButton(
onPressed: () => _openFileExplorer(),
child: new Text("Open file picker"),
),
),
new Builder(
builder: (BuildContext context) => isLoadingPath ? Padding(
padding: const EdgeInsets.only(bottom: 10.0),
child: const CircularProgressIndicator()
)
: path != null || paths != null ? new Container(
padding: const EdgeInsets.only(bottom: 30.0),
height: MediaQuery.of(context).size.height * 0.50,
child: new Scrollbar(
child: new ListView.separated(
itemCount: paths != null && paths.isNotEmpty ? paths.length : 1,
itemBuilder: (BuildContext context, int index) {
final bool isMultiPath = paths != null && paths.isNotEmpty;
final int fileNo = index + 1;
final String name = 'File $fileNo : ' +
(isMultiPath ? paths.keys.toList()[index] : fileName ?? '...');
final filePath = isMultiPath
? paths.values.toList()[index].toString() : path;
return new ListTile(title: new Text(name,),
subtitle: new Text(filePath),
);
},
separatorBuilder: (BuildContext context, int index) => new Divider(),
)),
)
: new Container(),
),
],
),
),
)),
),
);
}
}
Ensure a supported device is connected or emulator/simulator is started
Go to project directory
Use flutter run
command to run
flutter run
It builds and runs app on an available android/ios device