Looking for image picker on new flutter web 1.9. I found a way but for less than 1.9, now that is merged dont know how can i achived this. Tried with dart:html but is not working on release! Only on running
Asked
Active
Viewed 8,357 times
3 Answers
15
It seems like as for Flutter web 1.10 dev
, universal_html package is good candidate for the temporarily vacant position of dart:html
:
import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:universal_html/prefer_universal/html.dart' as html;
class ImagePickerLabPage extends StatefulWidget {
@override
_ImagePickerLabPageState createState() => _ImagePickerLabPageState();
}
class _ImagePickerLabPageState extends State<ImagePickerLabPage> {
String name = '';
String error;
Uint8List data;
pickImage() {
final html.InputElement input = html.document.createElement('input');
input
..type = 'file'
..accept = 'image/*';
input.onChange.listen((e) {
if (input.files.isEmpty) return;
final reader = html.FileReader();
reader.readAsDataUrl(input.files[0]);
reader.onError.listen((err) => setState(() {
error = err.toString();
}));
reader.onLoad.first.then((res) {
final encoded = reader.result as String;
// remove data:image/*;base64 preambule
final stripped =
encoded.replaceFirst(RegExp(r'data:image/[^;]+;base64,'), '');
setState(() {
name = input.files[0].name;
data = base64.decode(stripped);
error = null;
});
});
});
input.click();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(name),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.open_in_browser),
onPressed: () {
pickImage();
},
),
body: Center(
child: error != null
? Text(error)
: data != null ? Image.memory(data) : Text('No data...'),
),
);
}
}

Spatz
- 18,640
- 7
- 62
- 66
-
Thanks it's working fine, but how can we keep it's type as Image? I just wanna upload it to firebase, but it's not uploading as Image. – Shahzad Akram Dec 03 '19 at 04:44
-
html.InputReader and html.FileReader not importing successfully showing error there. Can you please let us know how to solve it? – Umair Jan 15 '20 at 09:33
-
1@Umair Make sure that you specified correct [package](https://pub.dev/packages/universal_html) in `pubspec.yaml`, and no other packages in your code imported with `html`-alias. – Spatz Jan 15 '20 at 11:37
-
Compiler message: lib/main.dart:240:5: Error: Factory redirects to class 'FileReader', which is abstract and can't be instantiated. Target kernel_snapshot failed: Exception: Errors during snapshot creation: null build failed. – Umair Jan 15 '20 at 12:51
-
@Umair You can create a new question. Show int it your `pubspec.yaml` and code from `lib/main.dart` file – Spatz Jan 15 '20 at 13:09
-
The solution that worked for me that i have changed my channel and make sure to use only that package in that code. Thankyou for your solutions – Umair Jan 16 '20 at 06:24
4
Actually onChange doesn't work well on mobile safari, it need to change addEventListener and also need to append it.
Future<void> _setImage() async {
final completer = Completer<List<String>>();
InputElement uploadInput = FileUploadInputElement();
uploadInput.multiple = true;
uploadInput.accept = 'image/*';
uploadInput.click();
// onChange doesn't work on mobile safari
uploadInput.addEventListener('change', (e) async {
// read file content as dataURL
final files = uploadInput.files;
Iterable<Future<String>> resultsFutures = files.map((file) {
final reader = FileReader();
reader.readAsDataUrl(file);
reader.onError.listen((error) => completer.completeError(error));
return reader.onLoad.first.then((_) => reader.result as String);
});
final results = await Future.wait(resultsFutures);
completer.complete(results);
});
// need to append on mobile safari
document.body.append(uploadInput);
final List<String> images = await completer.future;
setState(() {
_uploadedImages = images;
});
uploadInput.remove();
}
This also works:
Future<void> _setImage() async {
final completer = Completer<List<String>>();
final InputElement input = document.createElement('input');
input
..type = 'file'
..multiple = true
..accept = 'image/*';
input.click();
// onChange doesn't work on mobile safari
input.addEventListener('change', (e) async {
final List<File> files = input.files;
Iterable<Future<String>> resultsFutures = files.map((file) {
final reader = FileReader();
reader.readAsDataUrl(file);
reader.onError.listen((error) => completer.completeError(error));
return reader.onLoad.first.then((_) => reader.result as String);
});
final results = await Future.wait(resultsFutures);
completer.complete(results);
});
// need to append on mobile safari
document.body.append(input);
// input.click(); can be here
final List<String> images = await completer.future;
setState(() {
_uploadedImages = images;
});
input.remove();
}

Bulkin
- 1,020
- 12
- 27

user12208004
- 1,704
- 3
- 15
- 37
-
-
@Bulkin Thank you! saved me as image_picker_web has conflicts with iOS ( for device I use image_picker) and my app runs both on web and device. – Vincenzo Jul 11 '20 at 14:32
-
holy moly. you are my hero. How on earth did you figure this out? I figured that on mobile web the flutter code was somehow backgrounded during file selection... but I was totally lost on what to change. I need to understand your document.append better – Maksym Moros Aug 27 '20 at 15:16
2
why don't you just use: https://pub.dev/packages/image_picker_web
It supports also multiple outputTypes (File, Widget, Uint8List)

Rebar
- 1,076
- 10
- 19
-
I tried this, doesn't work, gives an unknown type on location. If somebody gets it to work, ket me know. It an issue in the package "issues" – Wesley Barnes Apr 16 '21 at 19:13
-