Newby Coder header banner

Flutter File Picker

Selecting file in Android/iOS using Flutter

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

Usage

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:

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

Creating new Flutter App

Check Flutter installation to setup Flutter

Use flutter create command to create a Flutter project (here file_picker_app :

flutter create file_picker_app

Dependency


Permission

Requesting permission to access external storage in Android

Find and open file_picker_app (project directory) → android → app → src → main → AndroidManifest.xml

Add READ_EXTERNAL_STORAGE permission (before <application tag)

file_picker_app/android/app/src/main/AndroidManifest.xml
<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" />

iOS

In iOS 11, user is prompted for permission when accessing photos

Files can be picked from iCloud without explicitly configuring Info.plist

App Code

file_picker_app/lib/main.dart
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(),
                ),
              ],
            ),
          ),
        )),
      ),
    );
  }
}

Run instructions

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


Screenshot/image

Android

cl-flutter-file-picker

iOS

cm-flutter-file-picker-as1cm-flutter-file-picker-as2cm-flutter-file-picker-as3