How to Select Multiple Images from Storage and display it in both Flutter and Flutter Web App?

Issue

I am working on this Flutter app that allows users to select multiple images from local storage to upload. Once the images are selected, it shows previews of all of them.

I could achieve this for a mobile Flutter app but I also need to target flutter web and this is not working for flutter web. I used this plugin as it allows to select multiple files for Flutter web also but it is returning List<html.File> which doesn’t allow me to read image bytes to display it in the UI.

I need a solution that:

  • allows selecting multiple images
  • works on flutter web as well
  • allows accessing image byte data so that I could display previews of them

Solution

You can copy paste run full code below
Before this pull request merge https://github.com/miguelpruivo/flutter_file_picker/pull/328/files/3e23d4e9977451d4e84f54a155ac1b2a951cd7fe
code snippet

Future<List<int>> fileAsBytes(html.File _file) async {
    final Completer<List<int>> bytesFile = Completer<List<int>>();
    final html.FileReader reader = html.FileReader();
    reader.onLoad.listen((event) => bytesFile.complete(reader.result));
    reader.readAsArrayBuffer(_file);
    return await bytesFile.future;
  }
  
ListView.separated(
        itemBuilder: (BuildContext context, int index) =>
            Column(
          children: [
            FutureBuilder<List<int>>(
                future: fileAsBytes(_files[index]),
                builder: (context, snapshot) => snapshot.hasData
                    ? Image.memory(snapshot.data)
                    : CircularProgressIndicator()),
            Text("name ${_files[index].name}"),
          ],
        ),

working demo
select two image file and display, do not check file type is image

enter image description here

full code

// ignore: avoid_web_libraries_in_flutter
import 'dart:async';
import 'dart:html';
import 'package:file_picker_web/file_picker_web.dart';
import 'package:flutter/material.dart';
import 'dart:html' as html;

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<html.File> _files = [];

  Future<List<int>> fileAsBytes(html.File _file) async {
    final Completer<List<int>> bytesFile = Completer<List<int>>();
    final html.FileReader reader = html.FileReader();
    reader.onLoad.listen((event) => bytesFile.complete(reader.result));
    reader.readAsArrayBuffer(_file);
    return await bytesFile.future;
  }

  void _pickFiles() async {
    _files = await FilePicker.getMultiFile() ?? [];
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              Expanded(
                child: _files.isNotEmpty
                    ? ListView.separated(
                        itemBuilder: (BuildContext context, int index) =>
                            Column(
                          children: [
                            FutureBuilder<List<int>>(
                                future: fileAsBytes(_files[index]),
                                builder: (context, snapshot) => snapshot.hasData
                                    ? Image.memory(snapshot.data)
                                    : CircularProgressIndicator()),
                            Text("name ${_files[index].name}"),
                          ],
                        ),
                        itemCount: _files.length,
                        separatorBuilder: (_, __) => const Divider(
                          thickness: 5.0,
                        ),
                      )
                    : Center(
                        child: Text(
                          'Pick some files',
                          textAlign: TextAlign.center,
                        ),
                      ),
              ),
              Padding(
                padding: const EdgeInsets.all(15.0),
                child: RaisedButton(
                  onPressed: _pickFiles,
                  child: Text('Pick Files'),
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

Answered By – chunhunghan

Answer Checked By – David Goodson (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *