5
votes

Sélecteur d'images Flutter Web 1.9

Vous recherchez un sélecteur d'images sur le nouveau flutter web 1.9. J'ai trouvé un moyen, mais pour moins de 1,9, maintenant qui est fusionné, je ne sais pas comment puis-je y parvenir. Essayé avec dart: html mais ne fonctionne pas à la sortie! Seulement en courant


0 commentaires

3 Réponses :


13
votes

Il semble que pour Flutter web 1.10 dev , le package universal_html est un bon candidat pour le poste temporairement vacant de 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...'),
      ),
    );
  }
}


6 commentaires

Merci, cela fonctionne bien, mais comment pouvons-nous garder son type comme image? Je veux juste le télécharger sur Firebase, mais ce n'est pas en tant qu'image.


html.InputReader et html.FileReader ne sont pas importés avec succès, indiquant une erreur. Pouvez-vous s'il vous plaît nous dire comment le résoudre?


@Umair Assurez-vous que vous avez spécifié le bon package dans pubspec.yaml , et qu'aucun autre package de votre code n'a été importé avec html -alias.


Message du compilateur: lib / main.dart: 240: 5: Erreur: Factory redirige vers la classe 'FileReader', qui est abstraite et ne peut pas être instanciée. Échec de la cible kernel_snapshot: exception: erreurs lors de la création de l'instantané: la génération nulle a échoué.


@Umair Vous pouvez créer une nouvelle question. Montrez-lui votre pubspec.yaml et le code du fichier lib/main.dart


La solution qui a fonctionné pour moi est d'avoir changé ma chaîne et de m'assurer de n'utiliser que ce package dans ce code. Merci pour vos solutions



3
votes

En fait, onChange ne fonctionne pas bien sur les safaris mobiles, il doit changer addEventListener et également l'ajouter.

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();
}

Cela fonctionne également:

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();
}


3 commentaires

Merci Bulkin, ça aide vraiment !!


@Bulkin Merci! m'a sauvé comme image_picker_web a des conflits avec iOS (pour l'appareil que j'utilise image_picker) et mon application fonctionne à la fois sur le Web et sur l'appareil.


Holy Moly. tu es mon héros. Comment diable avez-vous compris cela? J'ai pensé que sur le Web mobile, le code flottant était en quelque sorte en arrière-plan lors de la sélection de fichiers ... mais j'étais totalement perdu sur ce qu'il fallait changer. J'ai besoin de comprendre votre document.



1
votes

pourquoi n'utilisez-vous pas simplement: https://pub.dev/packages/image_picker_web

Il prend également en charge plusieurs types de sortie (fichier, widget, Uint8List)


0 commentaires