file_picker 1.3.8

pub package Awesome Flutter Codemagic build status

file_picker #

A package that allows you to use a native file explorer to pick single or multiple absolute file paths, with extensions filtering support.

Installation #

First, add file_picker as a dependency in your pubspec.yaml file.

file_picker: ^1.3.8

Android #


<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

before <application> to your app's AndroidManifest.xml file. This is required to access files from external storage.

iOS #

Based on the location of the files that you are willing to pick paths, you may need to add some keys to your iOS app's Info.plist file, located in <project root>/ios/Runner/Info.plist:

  • UIBackgroundModes with the fetch and remote-notifications keys - Required if you'll be using the FileType.ANY or FileType.CUSTOM. Describe why your app needs to access background taks, such downloading files (from cloud services). This is called Required background modes, with the keys App download content from network and App downloads content in response to push notifications respectively in the visual editor (since both methods aren't actually overriden, not adding this property/keys may only display a warning, but shouldn't prevent its correct usage).

  • NSAppleMusicUsageDescription - Required if you'll be using the FileType.AUDIO. Describe why your app needs permission to access music library. This is called Privacy - Media Library Usage Description in the visual editor.

     <string>Explain why your app uses music</string>
  • NSPhotoLibraryUsageDescription - Required if you'll be using the FileType.IMAGE or FileType.VIDEO. Describe why your app needs permission for the photo library. This is called Privacy - Photo Library Usage Description in the visual editor.

     <string>Explain why your app uses photo library</string>

Note: Any iOS version below 11.0, will require an Apple Developer Program account to enable CloudKit and make it possible to use the document picker (which happens when you select FileType.ALL, FileType.CUSTOM or any other option with getMultiFilePath()). You can read more about it here.

Usage #

There are only two methods that should be used with this package:

FilePicker.getFilePath() #

Will let you pick a single file. This receives two optional parameters: the fileType for specifying the type of the picker and a fileExtension parameter to filter selectable files. The available filters are:

  • FileType.ANY - Will let you pick all available files.
  • FileType.CUSTOM - Will let you pick a single path for the extension matching the fileExtension provided.
  • FileType.IMAGE - Will let you pick a single image file. Opens gallery on iOS.
  • FileType.VIDEO - WIll let you pick a single video file. Opens gallery on iOS.
  • FileType.AUDIO - Will let you pick a single audio file. Opens music on iOS. Note that DRM protected files won't provide a path, null will be returned instead.

FilePicker.getMultiFilePath() #

Will let you select multiple files and retrieve its path at once. Optionally you can provide a fileExtension parameter to filter the allowed selectable files. Will return a Map<String,String> with the files name (key) and corresponding path (value) of all selected files. Picking multiple paths from iOS gallery (image and video) aren't currently supported.

Usages #

So, a few example usages can be as follow:

// Single file path
String filePath;
filePath = await FilePicker.getFilePath(type: FileType.ANY); // will let you pick one file path, from all extensions
filePath = await FilePicker.getFilePath(type: FileType.CUSTOM, fileExtension: 'svg'); // will filter and only let you pick files with svg extension

// Pick a single file directly
File file = await FilePicker.getFile(type: FileType.ANY); // will return a File object directly from the selected file

// Multi file path
Map<String,String> filesPaths;
filePaths = await FilePicker.getMultiFilePath(); // will let you pick multiple files of any format at once
filePaths = await FilePicker.getMultiFilePath(fileExtension: 'pdf'); // will let you pick multiple pdf files at once
filePaths = await FilePicker.getMultiFilePath(type: FileType.IMAGE); // will let you pick multiple image files at once

List<String> allNames = filePaths.keys; // List of all file names
List<String> allPaths = filePaths.values; // List of all paths
String someFilePath = filePaths['fileName']; // Access a file path directly by its name (matching a key)
A few side notes #
  • Using getMultiFilePath() on iOS will always use the document picker (aka Files app). This means that multi picks are not currently supported for photo library images/videos or music library files.
  • When using FileType.CUSTOM, unsupported extensions will throw a MissingPluginException that is handled by the plugin.
  • On Android, when available, you should avoid using third-party file explorers as those may prevent file extension filtering (behaving as FileType.ANY). In this scenario, you will need to validate it on return.

Currently supported features #

  • [X] Load paths from cloud files (GDrive, Dropbox, iCloud)
  • [X] Load path from a custom format by providing a file extension (pdf, svg, zip, etc.)
  • [X] Load path from multiple files optionally, supplying a file extension
  • [X] Load path from gallery
  • [X] Load path from audio
  • [X] Load path from video
  • [X] Load path from any
  • [X] Create a File object from any selected file

If you have any feature that you want to see in this package, please add it here. 🎉

Demo App #


Example #

See example app.

Getting Started #

For help getting started with Flutter, view our online documentation.

For help on editing plugin code, view the documentation.

1.3.8 #

Bug fix: Fixes an issue that could cause a crash when picking files with very long names.

Changes: Updates Android target API to 29.

1.3.7 #

Rollback - Breaking change: Re-adds runtime verification for external storage read permission. Don't forget to add the permission to the AndroidManifest.xml file as well. More info in the README file.

Bug fix: Fixes a crash that could cause some Android API to crash when multiple files were selected from external storage.

1.3.6 #


  • Removes the Android write permissions requirement.
  • Minor improvements in the example app.
  • Now the exceptions are rethrown in case the user wants to handle them, despite that already being done in the plugin call.

1.3.5 #

Bug fix: Fixes an issue that could prevent users to pick files from the iCloud Drive app, on versions below iOS 11.

1.3.4+1 #

Rollback: Removes a local dependency that shouldn't have been committed with 1.3.4 which would cause Android build to fail.

1.3.4 #

Bug fix: Protects the registrar.activity() in the Android side of being accessed when it's null.

1.3.3 #

Bug fixes

  • Fixes an issue where sometimes a single file path was being returned as a List instead of String.
  • requestCode in Android intents are now restricted to 16 bits.

1.3.2 #

Bug fix: Returns a null value in the getFile() when the picker is canceled.

1.3.1 #

Bug fix: Fixes an issue on Android, where other activity would try to call FilePicker's result object when it shouldn't.

1.3.0 #

Breaking changes

  • FileType.CAMERA is no longer available, if you need it, you can use this package along with image_picker.

New features

  • You can now pick multiple files by using the getMultiFilePath() method which will return a Map<String,String> with all paths from selected files, where the key matches the file name and the value its path. Optionally, it also supports filtering by file extension, otherwise all files will be selectable. Nevertheless, you should keep using getFilePath() for single path picking.
  • You can now use FileType.AUDIO to pick audio files. In iOS this will let you select from your music library. Paths from DRM protected files won't be loaded (see README for more details).
  • Adds getFile() utility method that does the same of getFilePath() but returns a File object instead, for the returned path.

Bug fixes and updates

  • This package is no longer attached to the image_picker, and because of that, camera permission is also no longer required.
  • Fixes an issue where sometimes the InputStream wasn't being properly closed. Also, its exception is now being forward to the plugin caller.
  • Fixes an issue where the picker, when canceled, wasn't calling the result callback on the underlying platforms.

1.2.0 #

Breaking change: Migrate from the deprecated original Android Support Library to AndroidX. This shouldn't result in any functional changes, but it requires any Android apps using this plugin to also migrate if they're using the original support library.

1.1.1 #

  • Updates README file.

1.1.0 #

Breaking changes

  • FileType.PDF was removed since now it can be used along with custom file types by using the FileType.CUSTOM and providing the file extension (e.g. PDF, SVG, ZIP, etc.).
  • FileType.CAPTURE is now FileType.CAMERA

New features

  • Now it is possible to provide a custom file extension to filter file picking options by using FileType.CUSTOM

Bug fixes and updates

  • Fixes file names from cloud on Android. Previously it would always display Document
  • Fixes an issue on iOS where an exception was being thrown after canceling and re-opening the picker.
  • Fixes an issue where collision could happen with request codes on Android.
  • Adds public documentation to file_picker
  • Example app updated.
  • Updates .gitignore

1.0.3 #

  • Fixes build.gradle.

1.0.2 #

  • Minor update of README file.

1.0.1 #

  • Adds comments for public API

1.0.0 #

  • Version 1.0 release.
  • Adds support for ANY and VIDEO files.
  • Fixes an issue where permissions were recursively asked on Android.
  • Fixes an issue where some paths from document files couldn't be loaded with Android 8.0.
  • Updates README file to match changes.
  • General refactor & cleanup.

0.1.6 #

  • Replaces commons dependency with FilePath class on Android, to handle path resolution on different SDK.

0.1.5 #

  • Minor correction in the README file.

0.1.4 #

  • Changed Meta minimum version due to versioning conflict with flutter_localization.

0.1.3 #

  • Updated readme.

0.1.2 #

  • Changed license from Apache 2.0 to MIT.
  • Adds demo screenshot.

0.1.1 #

  • Adds license information (Apache 2.0).
  • Adds CHANGELOG details.

0.1.0 #

  • Initial release.
  • Supports picking paths from files on local storage, cloud.
  • Supports picking paths from both gallery & camera due to image_picker dependency.


import 'package:flutter/material.dart';

import 'package:flutter/services.dart';
import 'package:file_picker/file_picker.dart';

void main() => runApp(new FilePickerDemo());

class FilePickerDemo extends StatefulWidget {
  _FilePickerDemoState createState() => new _FilePickerDemoState();

class _FilePickerDemoState extends State<FilePickerDemo> {
  String _fileName;
  String _path;
  Map<String, String> _paths;
  String _extension;
  bool _multiPick = false;
  bool _hasValidMime = false;
  FileType _pickingType;
  TextEditingController _controller = new TextEditingController();

  void initState() {
    _controller.addListener(() => _extension = _controller.text);

  void _openFileExplorer() async {
    if (_pickingType != FileType.CUSTOM || _hasValidMime) {
      try {
        if (_multiPick) {
          _path = null;
          _paths = await FilePicker.getMultiFilePath(
              type: _pickingType, fileExtension: _extension);
        } else {
          _paths = null;
          _path = await FilePicker.getFilePath(
              type: _pickingType, fileExtension: _extension);
      } on PlatformException catch (e) {
        print("Unsupported operation" + e.toString());
      if (!mounted) return;

      setState(() {
        _fileName = _path != null
            ? _path.split('/').last
            : _paths != null ? _paths.keys.toString() : '...';

  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(
              children: <Widget>[
                new Padding(
                  padding: const EdgeInsets.only(top: 20.0),
                  child: new DropdownButton(
                      hint: new Text('LOAD PATH FROM'),
                      value: _pickingType,
                      items: <DropdownMenuItem>[
                        new DropdownMenuItem(
                          child: new Text('FROM AUDIO'),
                          value: FileType.AUDIO,
                        new DropdownMenuItem(
                          child: new Text('FROM IMAGE'),
                          value: FileType.IMAGE,
                        new DropdownMenuItem(
                          child: new Text('FROM VIDEO'),
                          value: FileType.VIDEO,
                        new DropdownMenuItem(
                          child: new Text('FROM ANY'),
                          value: FileType.ANY,
                        new DropdownMenuItem(
                          child: new Text('CUSTOM FORMAT'),
                          value: FileType.CUSTOM,
                      onChanged: (value) => setState(() {
                            _pickingType = value;
                            if (_pickingType != FileType.CUSTOM) {
                              _controller.text = _extension = '';
                new ConstrainedBox(
                  constraints: BoxConstraints.tightFor(width: 100.0),
                  child: _pickingType == FileType.CUSTOM
                      ? new TextFormField(
                          maxLength: 15,
                          autovalidate: true,
                          controller: _controller,
                              InputDecoration(labelText: 'File extension'),
                          keyboardType: TextInputType.text,
                          textCapitalization: TextCapitalization.none,
                          validator: (value) {
                            RegExp reg = new RegExp(r'[^a-zA-Z0-9]');
                            if (reg.hasMatch(value)) {
                              _hasValidMime = false;
                              return 'Invalid format';
                            _hasValidMime = true;
                            return null;
                      : new Container(),
                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(() => _multiPick = value),
                    value: _multiPick,
                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) =>
                      _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 String name = 'File $index: ' +
                                          ? _paths.keys.toList()[index]
                                          : _fileName ?? '...');
                                  final path = isMultiPath
                                      ? _paths.values.toList()[index].toString()
                                      : _path;

                                  return new ListTile(
                                    title: new Text(
                                    subtitle: new Text(path),
                                    (BuildContext context, int index) =>
                                        new Divider(),
                          : new Container(),

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:

  file_picker: ^1.3.8

2. Install it

You can install packages from the command line:

with Flutter:

$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:

import 'package:file_picker/file_picker.dart';
Describes how popular the package is relative to other packages. [more]
Code health derived from static analysis. [more]
Reflects how tidy and up-to-date the package is. [more]
Weighted score of the above. [more]
Learn more about scoring.

We analyzed this package on Aug 20, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.4.0
  • pana: 0.12.19
  • Flutter: 1.7.8+hotfix.4


Detected platforms: Flutter

References Flutter, and has no conflicting libraries.


Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0 <3.0.0
flutter 0.0.0
Transitive dependencies
collection 1.14.11 1.14.12
meta 1.1.6 1.1.7
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8