2

I want to upload multiple images into the Rest API. I tried the below code to upload a single image to the rest API. That is working fine, for multiple image selection I'm using multi_image_picker link, how can I modified below code to upload multiple images? Thank you

Future<String> uploadSingleImage(File file,String userid) async
  {

    final prefs = await SharedPreferences.getInstance();
    final key = 'token';
    final value = prefs.get(key ) ?? 0;

    String fileName = file.path.split("/").last;
    var stream =
    new http.ByteStream(DelegatingStream.typed(file.openRead()));

    // get file length

    var length = await file.length(); //imageFile is your image file
    Map<String, String> headers = {
      "Accept": "application/json",
      "Authorization": "Bearer $value"
    }; // ignore this headers if there is no authentication

    // string to uri
    var uri = Uri.parse(serverUrl + "/api/v1/upload_parent_image");

    // create multipart request
    var request = new http.MultipartRequest("POST", uri);

    // multipart that takes file
    var multipartFileSign = new http.MultipartFile('photo',
        stream,
        length,
        filename: fileName
    );

    // add file to multipart
    request.files.add(multipartFileSign);

    //add headers
    request.headers.addAll(headers);

    //adding params
    request.fields['id'] = userid;
   // request.fields['firstName'] = 'abc';
    // request.fields['lastName'] = 'efg';

    // send
    var response = await request.send();

    print(response.statusCode);

    // listen for response
    response.stream.transform(utf8.decoder).listen((value) {
      print(value);
    });
  }
Quick learner
  • 10,632
  • 4
  • 45
  • 55
FGH
  • 2,900
  • 6
  • 26
  • 59

5 Answers5

4

your Image list

List<String> photos = ["path of image1","path of image2", "path of image3",];



 List<http.MultipartFile> newList = [];

      for (var img in photos!) {
        if (img != "") {
          var multipartFile = await http.MultipartFile.fromPath(
            'Photos',
            File(img).path,
            filename: img.split('/').last,
          );
          newList.add(multipartFile);
        }
      }
request.files.addAll(newList);
Deepak Yadav
  • 227
  • 3
  • 4
3

You could pass a list of files to your method, loop over to build each MultipartFile objects and add them to your MultipartRequest

Future<String> uploadMultipleImage(List<File> files, String userid) async {
final prefs = await SharedPreferences.getInstance();
final key = 'token';
final value = prefs.get(key) ?? 0;

// string to uri
var uri = Uri.parse(serverUrl + "/api/v1/upload_parent_image");

// create multipart request
var request = new http.MultipartRequest("POST", uri);

for (var file in files) {
    String fileName = file.path.split("/").last;
    var stream = new http.ByteStream(DelegatingStream.typed(file.openRead()));

    // get file length

    var length = await file.length(); //imageFile is your image file

    // multipart that takes file
    var multipartFileSign = new http.MultipartFile('photo', stream, length, filename: fileName);

    request.files.add(multipartFileSign);
}

Map<String, String> headers = {
    "Accept": "application/json",
    "Authorization": "Bearer $value"
}; // ignore this headers if there is no authentication

//add headers
request.headers.addAll(headers);

//adding params
request.fields['id'] = userid;
// request.fields['firstName'] = 'abc';
// request.fields['lastName'] = 'efg';

// send
var response = await request.send();

print(response.statusCode);

// listen for response
response.stream.transform(utf8.decoder).listen((value) {
    print(value);
});
}
F Perroch
  • 1,988
  • 2
  • 11
  • 23
  • Happy to see these answers I'm struggling with the `multiple_image_pickers` I tried several libraries. even though most of the multiple-image picker libraries wasn't working perfectly. finally, I found a library(https://pub.dev/packages/multi_image_picker)libraries they using `Assets` , so are there any way to upload assets to the Rest API ? – FGH Mar 28 '20 at 12:53
  • Yo just have to send the files from the result of MultiMediaPicker.pickImages to the method and you're done normally – F Perroch Mar 28 '20 at 15:45
  • 3
    add brackets `[]` to make multiple images like `photo[]`. – Abed Putra Sep 22 '20 at 10:24
0

Well you are almost close to send multiple files at a time let me post some code

Future<String> uploadSingleImage(File file,File file2,String userid) async
  {

    final prefs = await SharedPreferences.getInstance();
    final key = 'token';
    final value = prefs.get(key ) ?? 0;

    String fileName = file.path.split("/").last;
    var stream =
    new http.ByteStream(DelegatingStream.typed(file.openRead()));

    // get file length    
    var length = await file.length(); //imageFile is your image file
    Map<String, String> headers = {
      "Accept": "application/json",
      "Authorization": "Bearer $value"
    }; // ignore this headers if there is no authentication

    // string to uri
    var uri = Uri.parse(serverUrl + "/api/v1/upload_parent_image");

    // create multipart request
    var request = new http.MultipartRequest("POST", uri);

    // multipart that takes file
    var multipartFileSign = new http.MultipartFile('photo',
        stream,
        length,
        filename: fileName
    );

    // add file to multipart
    request.files.add(multipartFileSign);


   // Now Adding file 2 in request
   String fileName2 = file2.path.split("/").last;
    var stream2 =
    new http.ByteStream(DelegatingStream.typed(file2.openRead()));
    var lengthOfFile2 = await file2.length(); 

   // multipart that takes file
    var multipartFile2 = new http.MultipartFile('file2_key_here',
        stream2,
        lengthOfFile2,
        filename: fileName2
    );

   // add file2 to multipart
    request.files.add(multipartFile2);

    //add headers
    request.headers.addAll(headers);

    //adding params
    request.fields['id'] = userid;
   // request.fields['firstName'] = 'abc';
    // request.fields['lastName'] = 'efg';

    // send
    var response = await request.send();

    print(response.statusCode);

    // listen for response
    response.stream.transform(utf8.decoder).listen((value) {
      print(value);
    });
  }
Quick learner
  • 10,632
  • 4
  • 45
  • 55
0

I have shared my code that i used to upload mutliple image with this packages

  multi_image_picker: ^4.8.0 
  flutter_absolute_path: ^1.0.6 
  flutter_image_compress:
  path_provider
http

flutter compress and path provider are used to compress the size

Http request code

static Future<String> uploadMultipleImage({List<File> files}) async {
// string to uri
    var uri = Uri.parse("your api url");
    print("image upload URL - $uri");
// create multipart request
    var request = new http.MultipartRequest("POST", uri);

    for (var file in files) {
      String fileName = file.path.split("/").last;
      var stream = new http.ByteStream(DelegatingStream.typed(file.openRead()));

      // get file length

      var length = await file.length(); //imageFile is your image file
      print("File lenght - $length");
      print("fileName - $fileName");
      // multipart that takes file
      var multipartFileSign = new http.MultipartFile('images[]', stream, length,
          filename: fileName);

      request.files.add(multipartFileSign);
    }

    Map<String, String> headers = {
      "Accept": "application/json",
      "Authorization":
          "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMiwiZXhwIjoxNjE3NTQyNDE0LCJpc3MiOiJsb2NhbGhvc3QiLCJpYXQiOjE2MTcxODI0MTR9.dGRbINOdx_tf417fpsjdQ5CR7uGULs98FjLGm2w4kRY"
    }; // ignore this headers if there is no authentication
    print("headers - $headers}");
//add headers
    request.headers.addAll(headers);

//adding params
    request.fields['heading'] = "heading";
    request.fields['description'] = "description";
    request.fields['mobile'] = "mobile";
    request.fields['email'] = "email";
    request.fields['category'] = "1";
    request.fields['location_type'] = "1";
    request.fields['location'] = "location";
    request.fields['lat'] = "12";
    request.fields['lng'] = "123";
    request.fields['price'] = "1231";
    request.fields['sub_category'] = "3";

// send
    var response = await request.send();

    print(response.statusCode);

    var res = await http.Response.fromStream(response);
    if (response.statusCode == 200 || response.statusCode == 201) {
      print("Item form is statuscode 200");
      print(res.body);
      var responseDecode = json.decode(res.body);

      if (responseDecode['status'] == true) {
        return res.body;
      } else {
        return res.body;
      }
    }

  }

My UI screen where I call the method

    import 'dart:convert';
    import 'dart:io';
    
    import 'package:flutter/material.dart';
    import 'package:flutter_absolute_path/flutter_absolute_path.dart';
    import 'package:flutter_image_compress/flutter_image_compress.dart';
    import 'package:lookapt_olx_app/service/ApiService.dart';
    import 'package:lookapt_olx_app/utils/Utils.dart';
    import 'package:lookapt_olx_app/utils/colorUtils.dart';
    import 'package:lookapt_olx_app/utils/fontUtils.dart';
    import 'package:lookapt_olx_app/widgets/appbar_widget.dart';
    import 'package:lookapt_olx_app/widgets/commonWidget.dart';
    import 'package:lookapt_olx_app/widgets/textFieldWidget.dart';
    import 'package:lookapt_olx_app/widgets/textWidgets.dart';
    import 'package:multi_image_picker/multi_image_picker.dart';
    import 'package:rounded_loading_button/rounded_loading_button.dart';
    
    import 'addNewPostController.dart';
    import 'multiImagePicker.dart';
    import 'package:path_provider/path_provider.dart' as path_provider;
    
    class AddNewPostScreen extends StatefulWidget {
      Map<String, dynamic> parameters;
      String categoryId;
    
      AddNewPostScreen({this.parameters, this.categoryId = ""});
    
      @override
      _AddNewPostScreenState createState() => _AddNewPostScreenState();
    }
    
    class _AddNewPostScreenState extends State<AddNewPostScreen> {
      @override
      void initState() {
        super.initState();
        print("add new post");
        print(widget.parameters['name']);
        print(widget.categoryId.toString());
      }
    
      List<Asset> images = [];
      String _error = "";
    
      Widget buildGridView() {
        if (images != null)
          return GridView.count(
            crossAxisCount: 3,
            crossAxisSpacing: 10,
            children: List.generate(images.length, (index) {
              Asset asset = images[index];
              return AssetThumb(
                asset: asset,
                width: 300,
                height: 300,
              );
            }),
          );
        else
          return Container(color: Colors.white);
      }
    
      Future<void> loadAssets() async {
        setState(() {
          images = List<Asset>();
        });
    
        List<Asset> resultList;
        String error;
    
        try {
          resultList = await MultiImagePicker.pickImages(
            maxImages: 3,
          );
        } on Exception catch (e) {
          error = e.toString();
        }
    
        // 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;
    
          if (error == null) _error = 'Selected images';
        });
      }
    
      /*
      Usage
    
       final dir = await path_provider.getTemporaryDirectory();
    
                    final targetPath = dir.absolute.path + "/temp.jpg";
                    File imgFile = await testCompressAndGetFile(
                        File(_capturedImage.path), targetPath);
    
      * */
    
      Future<File> testCompressAndGetFile(File file, String targetPath) async {
        print("testCompressAndGetFile");
        final result = await FlutterImageCompress.compressAndGetFile(
          file.absolute.path,
          targetPath,
          quality: 30,
          minWidth: 1024,
          minHeight: 1024,
          // rotate: 90,
        );
        print(file.lengthSync());
        print(result.lengthSync());
    
        return result;
      }
    
      _uploadImageFun() async {
        print("Note - _getImagePaths called");
        List<File> fileImageArray = [];
        images.forEach((imageAsset) async {
          final filePath =
              await FlutterAbsolutePath.getAbsolutePath(imageAsset.identifier);
    
          File tempFile = File(filePath);
          print(filePath);
          print("filePath.length  - ${filePath.length}");
          print(tempFile);
          print("tempFile.length() - ${tempFile.lengthSync()}");
    
          if (tempFile.existsSync()) {

          DateTime now = DateTime.now();

            final dir = await path_provider.getTemporaryDirectory();
            final targetPath =
          dir.absolute.path + "/lookaptPostImage${now.microsecond}.jpg";

            File imgFile =
                await testCompressAndGetFile(File(tempFile.path), targetPath); 

            print("Compressed image");
            print(imgFile.lengthSync());
            fileImageArray.add(imgFile); //with image compress
          }
          if (fileImageArray.length == images.length) {
            var res = await ApiService.uploadMultipleImage(files: fileImageArray);
            print("image upload response");
            print(res);
            var resp = json.decode(res);
            if (resp['status'] == true) {
              SuccessToastWidget(context, message: resp['message']);
            } else {
              FailedToastWidget(context, message: resp['message']);
            }
          }
        });
        print("Test Prints");
        print(fileImageArray.length);
    
        return fileImageArray;
      }
    
      final RoundedLoadingButtonController _loginBtnController =
          new RoundedLoadingButtonController();
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: CommonAppBarWidget(title: widget.parameters['name'] ?? ""),
          body: _body(),
        );
      }
    
      AddNEwPostController _addNEwPostController = new AddNEwPostController();
    
      Widget _body() {
        return Padding(
          padding: const EdgeInsets.only(left: 20, right: 20, top: 10),
          child: ListView(
            children: [
            
              InkWell(
                onTap: loadAssets,
                child: ClipRRect(
                  borderRadius: BorderRadius.circular(10),
                  child: Container(
                    color: Colors.grey.shade400,
                    child: ListTile(
                      leading: Icon(
                        Icons.add_box_outlined,
                        size: 30,
                        color: Colors.black,
                      ),
                      trailing: MyTextWidgets.textWidgetSemiBold(
                          str: "Pick Images", fontSize: 20),
                    ),
                  ),
                ),
              ),
              RoundedLoadingButton(
                child: MyTextWidgets.textWidgetBold(
                    fontSize: 16, str: "Next", color: MyColors.white.redC),
                controller: _loginBtnController,
                onPressed: () {
                  _getImagePaths();                 
                },
                width: MediaQuery.of(context).size.width,
                borderRadius: 10,
                color: MyColors.appGreenColor.redC,
                height: 44,
              ),
              Center(
                  child: _error == ""
                      ? Container()`enter code here`
                      : MyTextWidgets.textWidgetLight(str: _error)),
   
              Container(
                child: buildGridView(),
                height: 100,
                width: MediaQuery.of(context).size.width - 100,
              ),
             
            ],
          ),
        );
      }


}

NOTE:

My ui code may not run in your code so only copy the required code from the Screen code.

Http request code will work fine just copy and past it

Thank for you support!

abhijith k
  • 369
  • 4
  • 4
  • If your image get overrited use below code to add file path. final targetPath = dir.absolute.path + "/lookaptPostImage${now.microsecond}.jpg"; here i add a microseccond with file path then the issue will solve – abhijith k Mar 31 '21 at 12:41
  • declare the now vaiable like DateTime now = DateTime.now(); above before adding the line – abhijith k Mar 31 '21 at 12:42
0

I am posting this solution with dio and image_picker dependency. And it will definitely work. I have spent 2 days for this solution.

FormData formData = new FormData.fromMap({
  "name": "Max",
  "location": "Paris",
  "age": 21,
  "image[]": [
    await MultipartFile.fromFile(
      _imageFile.path,
    ),
    await MultipartFile.fromFile(
      _imageFile.path,
    ),
  ],
});

print(FormData1().then((value) {
  print(value);
}));
response = await dio.post(
 
  "http://143.110.244.110/radius/frontuser/eventsubmitbutton",
  data: formData,
  onSendProgress: (received, total) {
    if (total != -1) {
      print((received / total * 100).toStringAsFixed(0) + '%');
    }
  },
);
print(response);