Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to upload multiple images using Dio and multi_image_picker plugin in Flutter

I want to upload multiple-images using Dio and multi_image_picker plug-in in Flutter.

List<Asset> this is the problem because I can't convert from List<Asset> to List<File> so if you have any solutions help me.

try to use:

  1. multi_image_picker: ^4.6.1

  2. dio: ^3.0.4

Thanks

Bona SR.

import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:merchantside/helper/colorhelper.dart';
import 'package:merchantside/merchantside/login.dart';
import 'dart:async';
import 'package:multi_image_picker/multi_image_picker.dart';

class ListImages extends StatefulWidget {
  String errorMessage = "";
  @override
  _ListImagesState createState() => new _ListImagesState();
}

class _ListImagesState extends State<ListImages> {
  List<Asset> images = List<Asset>();
  List<File> listImages = [];
  @override
  void initState() {
    super.initState();
  }

  Widget buildGridView() {
    return GridView.count(
      crossAxisCount: 3,
      children: List.generate(images.length, (index) {
        Asset asset = images[index];
        return AssetThumb(
          asset: asset,
          width: 300,
          height: 300,
        );
      }),
    );
  }


  void _uploadFiles() async {
    String uid = await FlutterSecureStorage().read(key: "getTocken");
    try {
      var dio = Dio();
      FormData formData = new FormData.fromMap({
        "pictures[]": images, 
      });
      Response resp = await dio.post(
        mainUrl + 'merchant/upload-galleries',
        data: formData,
        onSendProgress: (int sent, int total) {
          //
        }, 
        options: Options(
          headers: {
            HttpHeaders.authorizationHeader: uid,
          },
        )
      );
      if(resp.statusCode == 200) {
        print("============= Print Resp data: ");
        print(resp.data);
      }

    } catch (e) {
      print(e);
    }
  }

  Future<void> loadAssets() async {
    List<Asset> resultList = List<Asset>();
    try {
      resultList = await MultiImagePicker.pickImages(
        maxImages: 6,
        enableCamera: true,
        selectedAssets: images,
        cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
        materialOptions: MaterialOptions(
          actionBarColor: "#abcdef",
          actionBarTitle: "Example App",
          allViewTitle: "All Photos",
          useDetailsView: false,
          selectCircleStrokeColor: "#000000",
        ),
      );
    } on Exception catch (e) {
      print(e);
    }

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;
    setState(() {
      images = resultList;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        heroTag: "btn1",
        backgroundColor: ColorHelper.orange,
        child: Icon(Icons.add_photo_alternate),
        onPressed: loadAssets,
      ),
      appBar: new AppBar(
        title: Text('បញ្ជីរូបភាព'),
        backgroundColor: ColorHelper.orange,
      ),
      body: Column(
        children: <Widget>[
          //Error message
          errorMessage != "" ? 
          Container(
            margin: EdgeInsets.only(left: 10, right: 10, top: 10),
            height: 50,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.all(Radius.circular(4)),
              color: ColorHelper.red.withOpacity(0.5),
            ),
            child: Center(
              child: Text("$errorMessage", style: TextStyle(color: ColorHelper.swhite, fontSize: 15),),
            ),
          ):
          Container(),

          Expanded(
            child: Container(
              margin: EdgeInsets.only(left: 10, right: 10, top: 10),
              child: buildGridView(),
            ),
          ),
          SafeArea(
            child: Container(
              margin: EdgeInsets.all(10),
              decoration: BoxDecoration(
                color: ColorHelper.green,
                borderRadius: BorderRadius.all(Radius.circular(4))
              ),
              height: 50,
              child: InkWell(
                onTap: () {
                  if(images.length > 0) {
                    setState(() {
                      errorMessage = "";
                    });
                    // Call function upload multiple files
                    _uploadFiles();
                  } else {
                    setState(() {
                      errorMessage = "សូមបញ្ជូលរូបភាព";
                    });
                  } 
                },
                child: Center(
                  child: Text("រួចរាល់", style: TextStyle(color: ColorHelper.swhite, fontSize: 15, fontWeight: FontWeight.w500,),),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}
like image 282
sreng bona Avatar asked Jan 17 '20 02:01

sreng bona


3 Answers

when you pick images from gallery, called getFileList() and then called set state,first use global variable of list of file and clear each time this list when you again pick images.

  List<File> listFile = List<File>();
  images = resultList;
  _error = error;
   getFileList();

 void getFileList() async{
  listFile.clear();
 for(int i=0; i<images.length; i++){
  var path= await images[i].filePath;
  print(path);
  var file=await getImageFileFromAssets(path);
  print(file);
  listFile.add(file);
}
 setState(() {

 });
}

getImageFileFromAsset is used for conver asset to file

Future<File> getImageFileFromAsset(String path) async {
final file = File(path);
return file;

}

and use listFile in formdata.

like image 91
Avinash Avatar answered Nov 16 '22 08:11

Avinash


Here's how to get a list of byte arrays from a list of Assets:

List<Asset> images;
...

List<ByteData> byteDataList = await Future.wait(images.map((Asset image) => image.getByteData()));

List<Uint8List> byteArrayList = byteDataList.map((ByteData byteData) {
  ByteBuffer byteBuffer = byteData.buffer;
  return byteBuffer.asUint8List(byteData.offsetInBytes, byteBuffer.lengthInBytes);
}).toList();

Now you can use the list of byte arrays to build a payload using your network client of choice. For those not using 3rd party networking clients, that would be a MultipartRequest with multiple MultipartFile.fromBytes.

like image 29
Ovidiu Avatar answered Nov 16 '22 09:11

Ovidiu


You don't need to convert Asset into File, You can send is as a byte array.

Only need to create the Multipart object of each image.

You can get the byte array from the Assets

 ByteData byteData = await asset.getByteData();
  List<int> imageData = byteData.buffer.asUint8List();

then it can pass through MultipartFile.fromBytes() method.

so it will look like,

  String url = "upload/url";

          List<Asset> images = List<Asset>();
          List<MultipartFile> multipartImageList = new List<MultipartFile>();
          if (null != images) {
            for (Asset asset in images) {
              ByteData byteData = await asset.getByteData();
              List<int> imageData = byteData.buffer.asUint8List();
              MultipartFile multipartFile = new MultipartFile.fromBytes(
                imageData,
                filename: 'load_image',
                contentType: MediaType("image", "jpg"),
              );
              multipartImageList.add(multipartFile);
            }

            FormData formData = FormData.fromMap({
              "multipartFiles": multipartImageList,
              "userId": '1'
            });

            Dio dio = new Dio();
            var response = await dio.post(url, data: formData);
          }

FYI

like image 1
ajay Avatar answered Nov 16 '22 10:11

ajay