How to Pick files and Images for upload with flutter web

32,464

Solution 1

Using dart:html package directly in Flutter is not recommended.

Instead, use this package: https://pub.dev/packages/file_picker.

Example of how to use in Flutter Web:

class FileUploadButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      child: Text('UPLOAD FILE'),
      onPressed: () async {
        var picked = await FilePicker.platform.pickFiles();

        if (picked != null) {
          print(picked.files.first.name);
        }
      },
    );
  }
}

Note that FilePickerResult.path is not supported in Flutter Web.

Solution 2

I tried the code below and it worked.

first import 'dart:html';

// variable to hold image to be displayed 

      Uint8List uploadedImage;

//method to load image and update `uploadedImage`


    _startFilePicker() 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) {
                    setState(() {
                      uploadedImage = reader.result;
                    });
        });

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

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

now just any Widget, like a button and call the method _startFilePicker()

Solution 3

import 'package:http/http.dart' as http;
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';

class FileUploadWithHttp extends StatefulWidget {
  @override
  _FileUploadWithHttpState createState() => _FileUploadWithHttpState();
}

class _FileUploadWithHttpState extends State<FileUploadWithHttp> {
  PlatformFile objFile = null;

  void chooseFileUsingFilePicker() async {
    //-----pick file by file picker,

    var result = await FilePicker.platform.pickFiles(
      withReadStream:
          true, // this will return PlatformFile object with read stream
    );
    if (result != null) {
      setState(() {
        objFile = result.files.single;
      });
    }
  }

  void uploadSelectedFile() async {
    //---Create http package multipart request object
    final request = http.MultipartRequest(
      "POST",
      Uri.parse("Your API URL"),
    );
    //-----add other fields if needed
    request.fields["id"] = "abc";

    //-----add selected file with request
    request.files.add(new http.MultipartFile(
        "Your parameter name on server side", objFile.readStream, objFile.size,
        filename: objFile.name));

    //-------Send request
    var resp = await request.send();

    //------Read response
    String result = await resp.stream.bytesToString();

    //-------Your response
    print(result);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: [
          //------Button to choose file using file picker plugin
          RaisedButton(
              child: Text("Choose File"),
              onPressed: () => chooseFileUsingFilePicker()),
          //------Show file name when file is selected
          if (objFile != null) Text("File name : ${objFile.name}"),
          //------Show file size when file is selected
          if (objFile != null) Text("File size : ${objFile.size} bytes"),
          //------Show upload utton when file is selected
          RaisedButton(
              child: Text("Upload"), onPressed: () => uploadSelectedFile()),
        ],
      ),
    );
  }
}

Solution 4

I've tested this package and was very happy with the result imagePickerWeb it returns 3 different types it can be in the form of Image(widget for preview), byte, File(upload)

then you can use this to get the values

html.File _cloudFile;
 var _fileBytes;
 Image _imageWidget;
 
 Future<void> getMultipleImageInfos() async {
    var mediaData = await ImagePickerWeb.getImageInfo;
    String mimeType = mime(Path.basename(mediaData.fileName));
    html.File mediaFile =
        new html.File(mediaData.data, mediaData.fileName, {'type': mimeType});

    if (mediaFile != null) {
      setState(() {
        _cloudFile = mediaFile;
        _fileBytes = mediaData.data;
        _imageWidget = Image.memory(mediaData.data);
      });
    }

Uploading to firebase

don't forget to add this to your index.html

  <script src="https://www.gstatic.com/firebasejs/7.5.0/firebase-storage.js"></script>

Uploading to firebase

import 'package:firebase/firebase.dart' as fb;
    uploadToFirebase(File file) async {

    final filePath = 'temp/${DateTime.now()}.png';//path to save Storage
    try {
      fb
          .storage()
          .refFromURL('urlFromStorage')
          .child(filePath)
          .put(file);
    } catch (e) {
      print('error:$e');
    }
  }

See the documentation of the package if you still have problems

Solution 5

The accepted answer is indeed outdated. Like jnt suggested, https://pub.dev/packages/file_picker is a handy package, when it comes to implementing an image upload using Flutter Web.

The problem I was facing is to get a base64 representation of an image, since I was using it to store images in Firestore. As we know, dart:io is not supported on Flutter Web and throws Unsupported operation: _Namespace error. Hence, using File and reading file's bytes was not an option. Luckily, the package provides API to convert the uploaded image to Uint8List. Here is my implementation:

import 'package:file_picker/file_picker.dart';

...

FilePickerResult? pickedFile;

...

void chooseImage() async {
    pickedFile = await FilePicker.platform.pickFiles();
    if (pickedFile != null) {
      try {
        setState(() {
          logoBase64 = pickedFile!.files.first.bytes;
        });
      } catch (err) {
        print(err);
      }
    } else {
      print('No Image Selected');
    }
}

In case you need to display the local image right away, use Image.memory.

Image.memory(logoBase64!);
Share:
32,464
Norbert
Author by

Norbert

I am a passionate software developer who develops desktop,web and mobile(android&amp;iOS with Flutter) software I am familiar with the following Dart Flutter Nodejs Reactjs Php mySQL Python html css

Updated on January 27, 2022

Comments

  • Norbert
    Norbert about 2 years

    I would like to know how to pick an Image from the users computer into my flutter web app for upload

  • grantespo
    grantespo over 3 years
    This repo has been archived by the owner
  • Abdul Rafay
    Abdul Rafay over 3 years
    is there a way to detect if the file picker was canceled?
  • C. Skjerdal
    C. Skjerdal over 3 years
    @AbdulRafay my understanding for Web there isn't any cancelled callback.
  • Dean Villamia
    Dean Villamia over 3 years
    you could still fork the repo here github.com/Ahmadre/image_picker_web
  • sta
    sta over 3 years
    Please add more details about your answer
  • Rahul Kushwaha
    Rahul Kushwaha about 3 years
    I am using this dependencies but not getting path .I have to upload it to firebase . THen what to use for flutter web to select file path for web
  • Rahul Kushwaha
    Rahul Kushwaha about 3 years
    Can we use it for flutter web
  • jnt
    jnt about 3 years
    This works in flutter web, but path is not needed, and is not implemented, as stated explicitly in the docs. Just use the PlatformFile.bytes property to access the bytes.
  • Lad Khushbu
    Lad Khushbu about 3 years
    @RahulKushwaha Yes! It is working well in flutter web.
  • Rahul Kushwaha
    Rahul Kushwaha about 3 years
    @LadKhushbu It's giving me null aas path when choosing any .docs file .I am using pub.dev/packages/file_picker package.
  • Lad Khushbu
    Lad Khushbu about 3 years
    @RahulKushwaha Yes it will return null path in web, so use ReadStream to upload file.
  • Rahul Kushwaha
    Rahul Kushwaha about 3 years
    @LadKhushbu can you please share me details me how to use read stream and ?
  • Wesley Barnes
    Wesley Barnes about 3 years
    I'm finding it pretty hard to get an image uploaded with flutter web. This solution also gives error - <error>:<getObject: NoSuchMethodError: The getter 'uri' was called on null.> - Anyone know maybe why please?
  • Yogi Arif Widodo
    Yogi Arif Widodo over 2 years
    why i always get null on .bytes ?
  • Yogi Arif Widodo
    Yogi Arif Widodo over 2 years
    the request mimetype is application/octet-stream not image .
  • AzureIP
    AzureIP over 2 years
    Multipart request needs a Stream<List<int>>. How to get this from .bytes?
  • AzureIP
    AzureIP over 2 years
    ByteStream.fromBytes(bytes!.toList())
  • AzureIP
    AzureIP over 2 years
    How to deal with large files? This works only for around up to 537MB.
  • Santiago
    Santiago about 2 years
    This is the easy part, you missed how to send it trough http and most importantly how to handle it on the server.
  • Benyamin
    Benyamin about 2 years
    @LadKhushbu can you update this answer with null safety? in the readstream line it shows this error: Stream<List<int>>?' can't be assigned to the parameter type 'Stream<List<int>>
  • Benyamin
    Benyamin about 2 years
    it shows this error for me: Unsupported operation: Platform._operatingSystem
  • Jeff Frazier
    Jeff Frazier about 2 years
    Agree with Santiago. This is easy, it's converting the bytes back to a File to upload to AWS that is hard to find an answer for.
  • Abdallah Ibrahim
    Abdallah Ibrahim almost 2 years
    @Benyamin did you manage to convert this to null safety friendly? I am stuck on the same issue now..
  • Abdallah Ibrahim
    Abdallah Ibrahim almost 2 years
    OK got it, it works for me now, need to put objFile!.readStream!