Je souhaite télécharger plusieurs images à l'aide de Dio et du plug-in multi_image_picker dans Flutter.
List<Asset>
c'est le problème car je ne peux pas convertir à partir de List<Asset>
à List<File>
donc si vous avez des solutions, aidez-moi.
essayez d'utiliser:
multi_image_picker: ^4.6.1
dio: ^3.0.4
Merci
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,),),
),
),
),
),
],
),
);
}
}
lorsque vous choisissez des images de la galerie, appelées getFileList () puis appelées set state, utilisez d'abord la variable globale de la liste de fichiers et effacez à chaque fois cette liste lorsque vous sélectionnez à nouveau des 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 est utilisé pour convertir l'actif en fichier
Future<File> getImageFileFromAsset(String path) async {
final file = File(path);
return file;
}
et utilisez listFile dans formdata.
Voici comment obtenir une liste de tableaux d'octets à partir d'une liste de Asset
s:
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();
Vous pouvez maintenant utiliser la liste des tableaux d'octets pour créer une charge utile à l'aide du client réseau de votre choix. Pour ceux qui n'utilisent pas de clients réseau tiers, ce serait un MultipartRequest
avec plusieurs MultipartFile.fromBytes
.
Vous pouvez utiliser file_picker et obtenir la liste des fichiers sélectionnés directement. Il prend en charge la sélection multiple et fournit le chemin du fichier en réponse. Ce sera le moyen le plus simple.
List<File> files = await FilePicker.getMultiFilePath(
type: FileType.IMAGE);
J'ai utilisé le plugin dio et multi_image dans mon application et cela fonctionne correctement. Ce que je fais, c'est donner mes extraits de code ici. Vous pouvez dire que c'est une version fonctionnelle et qu'elle devrait fonctionner dans n'importe quelle application.
classe de bloc
final imageController = BehaviorSubject<List<Asset>>();
StreamSink<List<Asset>> get sinkImages =>
imageController.sink;
Stream<List<Asset>> get getImages => imageController.stream;
Future<void> loadImages(imageCount) async {
List<Asset> imageList = List<Asset>();
String error = 'No Error Dectected';
try {
imageList = await MultiImagePicker.pickImages(
maxImages: imageCount,
enableCamera: true,
cupertinoOptions: CupertinoOptions(
takePhotoIcon: "chat",
),
materialOptions: MaterialOptions(
actionBarColor: "#0A73B1",
statusBarColor: "#0A73B1",
actionBarTitle: "Select Image",
allViewTitle: "All Photos",
useDetailsView: false,
selectCircleStrokeColor: "#000000",
),
);
} on Exception catch (e) {
error = e.toString();
print(error);
}
_error = error;
imageController.add(imageList);
}
// appelez cette méthode lorsque vous lancez un appel API
Future<GenericResponse> uploadImageRequest() async {
RequestModel reqModel = RequestModel(
uploadImageList: getImages);
final SharedPref prefs = SharedPref();
String token = await prefs.readString(accessToken);
GenericResponse response = await _application.repository
.uploadRequest(reqModel: reqModel, accessToken: token);
return response;
}
Donc, vous avez déjà votre liste d'images par ceci. Et définissez également ces listes dans votre classe de modèle de demande. Maintenant, envoyons ces images en plusieurs parties en utilisant dio.
Méthode de classe API
// appel depuis la classe du référentiel
Future<GenericResponse> uploadRequest(
{RequestModel reqModel, String accessToken}) async {
return await _apiProvider.uploadRequest(
reqModel: reqModel, accessToken: accessToken);
}
// télécharger une demande d'API d'image
Future<ResponseModel> uploadRequest(
{RequestModel requestModel, String accessToken}) async {
List<MultipartFile> imageList = [];
imageList = await getMultiPartImages(requestModel.imageList);
FormData formData = FormData.fromMap(RequestModel(
uploadImageList: imageList,
.toJson());
try {
Response response = await getDio().post(
'api/endpoint',
options: Options(headers: {
'Authorization': 'Bearer $accessToken',
}),
data: formData,
);
return ResponseModel.fromJson(response.data);
} catch (error, stacktrace) {
debugPrint("Exception occured: $error stackTrace: $stacktrace");
return ResponseModel.withError(handleError(error));
}
}
// classe de modèle podo
class RequestModel {
var uploadImageList;
RequestModel(
{this.uploadImageList});
RequestModel.fromJson(Map<String, dynamic> json) {
uploadImageList = json['image_list'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['image_list'] = this.uploadImageList;
return data;
}
@override
String toString() {
return toJson().toString();
}
}