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!