2

Flutter web is still in technical preview but i want to pick an image from the disk and upload it to the server. Is there anyway to add HTML, JS to my flutter web project and interact with it?

M.Ali
  • 8,815
  • 5
  • 24
  • 42

3 Answers3

1

You need addEventListener and also need to append it for woking it on mobile safari. I answered here too.

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();
}
user12208004
  • 1,704
  • 3
  • 15
  • 37
0

This will do what you want for web. Just call it from any button and it will open the system dialog to chose the file.

import 'dart:typed_data';
import 'package:universal_html/prefer_sdk/html.dart';    
import '../../../providers/form_provider.dart';

Uint8List uploadedImage;

startFilePickerWeb(ProviderForm formProvider) async {    
  InputElement uploadInput = FileUploadInputElement();
  uploadInput.click();

  uploadInput.onChange.listen((e) {
    // read file content as dataURL
    final files = uploadInput.files;
    if (files.length == 1) {
      final file = files[0];
      FileReader reader = FileReader();

      reader.onLoadEnd.listen((e) {
      //Here I send the imatge to my Provider 
        formProvider.setLogoEmpresa(reader.result);
      });

      reader.onError.listen((fileEvent) {
        print("Some Error occured while reading the file");
      });

      reader.readAsArrayBuffer(file);
    }
  });
}

The provider:

class ProviderForm extends ChangeNotifier {
    Uint8List logoEmpresa;
    void setLogoEmpresa(Uint8List newFile) {
       logoEmpresa = newFile;
       notifyListeners();
    }
}

Then in your view you can render it like this, in case no imatge it show a attachement icon:

Container(
      width: formProvider.logoEmpresa == null
          ? 70.0
          : 90.0,
      child: formProvider.logoEmpresa == null
          ? Icon(
              Icons.attach_file,
              size: 70.0,
              color: kColorPrincipal,
            )
          : Image.memory(formProvider.logoEmpresa,
              fit: BoxFit.fitWidth),
    ),

If you have any question, please ask and I'll do my best to help.

Daniel
  • 1,007
  • 1
  • 11
  • 23
  • how to use it for sending file? – kira Jun 12 '20 at 05:23
  • It depends what you understand with sending. Do you want to share with platform specific share action? there're some packages for that, do you want to upload to an API? Then use the post action there... be more specific add if I can help I will. – Daniel Jun 12 '20 at 06:51
0

You can use image_picker_web :

dependencies:
  image_picker_web: ^1.0.9

picks Images (as Widget, File or Uint8List) and Videos (as File or Uint8List)

Rudresh Narwal
  • 2,740
  • 3
  • 11
  • 21