FlioでDioとmulti_image_pickerプラグインを使用して複数の画像をアップロードしたい。
List<Asset>
から変換できないため、これが問題ですList<Asset>
からList<File>
そのため、解決策がある場合は私を助けてください。
使用してみてください:
multi_image_picker: ^4.6.1
dio: ^3.0.4
ありがとう
ボナ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,),),
),
),
),
),
],
),
);
}
}
ギャラリーから画像を選択してgetFileList()を呼び出し、次にset stateを呼び出した場合、最初にファイルのリストのグローバル変数を使用し、画像を再度選択するときにこのリストを毎回クリアします。
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は、アセットをファイルに変換するために使用されます
Future<File> getImageFileFromAsset(String path) async {
final file = File(path);
return file;
}
formdataでlistFileを使用します。
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();
これで、バイト配列のリストを使用して、選択したネットワーククライアントを使用してペイロードを構築できます。サードパーティのネットワーククライアントを使用していない場合は、MultipartRequest
に複数のMultipartFile.fromBytes
。
file_picker を使用して、直接選択されたファイルのリストを取得できます。複数選択をサポートし、応答としてファイルパスを提供します。それが最も簡単な方法です。
List<File> files = await FilePicker.getMultiFilePath(
type: FileType.IMAGE);
私は私のアプリでdioとmulti_imageプラグインを使用し、正しく動作しました。ここで私のコードスニペットを提供しています。これは動作バージョンであり、どのアプリでも動作するはずです。
ブロッククラス
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);
}
// 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;
}
だから、あなたはすでにこれによってあなたのイメージリストを得ました。また、これらのリストをリクエストモデルクラスに設定します。次に、これらの画像をdioを使用してマルチパートとして送信します。
APIクラスメソッド
//リポジトリクラスから呼び出す
Future<GenericResponse> uploadRequest(
{RequestModel reqModel, String accessToken}) async {
return await _apiProvider.uploadRequest(
reqModel: reqModel, accessToken: accessToken);
}
//画像APIリクエストをアップロード
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));
}
}
//ポドモデルクラス
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();
}
}