Upload images list with dio - flutter

I've use this code in my application with Dio: 2.2.2 and it works fine, but after upgrading my Dio package version, I must use the MultipartFile option. I tried to use it, but all data sent ok without the images. How can I upgrade this code to use with the latest Dio package version?
Old code:
Future add(name,desc,address,images) async {
Map ad_data;
await dio
.post("${host}/add",
data: FormData.from({
"name": "${name}",
"desc": "${desc}",
"address": "${address}",
"image[]": images
.map((image) =>
UploadFileInfo(File(image.path), basename(image.path)))
.toList(),
}),).then((data) {
ad_data = data.data;
});
return ad_data;
}

Update your add function with the below one... I am using dio: ^4.0.0.
import 'package:path/path.dart';
Future add(name,desc,address,images) async {
var formData = FormData.fromMap({
'name': name,
'desc': desc,
'address': address,
'files': [
for (var item in images)
{
await MultipartFile.fromFile(item.path,
filename: basename(item.path))
}.toList()
],
});
await dio.post("${host}/add",data:formData).then((data) {
ad_data = data.data;
});
return ad_data;
}

I have a costum function for uploading one file, you can change it and use.
Dio getBaseDio() {
var token = "AccessToken";
Dio dio = Dio(BaseOptions(
baseUrl: "your base url",
headers: {
"Authorization": "Bearer $token",
"Accept": "application/json",
}));
return dio;
}
after this :
Future<Response> postWithFile(
String url,
dynamic body) async {
return await getBaseDio().post(url, data: body)
.catchError(
(error) {
return error.response;
},
);
}
now you can use postWithFile function like this:
FormData formData = FormData.fromMap({
"param1": "value1",
"param2": "value2,
"fileParam": await MultipartFile.fromFile(attachPath, filename: fileName),
});
var result = await postWithFile(url, formData);
I hope I was able to help.

add content type
contentType: MediaType(
"image", "${item.path.split(".").last}"),

Related

Cannot upload image using dio post request

I am trying to upload a photo with caption to REST API. But since it is my first time, I am getting some exceptions. My code for uploading the image is shown below:
Dio dio = new Dio();
dio.options.headers['content-Type'] = 'multipart/form-data';
dio.options.headers['Authorization'] = 'Token ${box.get('token')}';
FormData formData = FormData.fromMap({
"author": box.get('user_id'),
"description": _caption,
"image": MultipartFile.fromFileSync(_image.path,
filename: _image.path.split(Platform.pathSeparator).last)
});
dio
.post("$baseURL/posts/create/",
data: formData,
options:
Options(method: 'POST', responseType: ResponseType.plain))
.then((response) => print(response))
.catchError((error) => print(error));
After I run this on my device and try to upload image, it directs me to dio.dart package line throw assureDioError(e, options);
If you have any knowledge with uploading images using dio, kindly help solve it.
UPDATED: body of json
{
"author": null,
"description": "",
"image": null
}
UPDATED: I tried with another service uploading image (not dio)
// string to uri
var uri = Uri.parse("$baseURL/posts/create/");
// create multipart request
var request = http.MultipartRequest("POST", uri);
// add headers with Auth token
Map<String, String> headers = {
"Authorization": "Token ${box.get('token')}",
"Content-type": "multipart/form-data"
};
request.headers.addAll(headers);
// add fields
Map<String, String> fields = {
'author': box.get('user_id').toString(),
'description': _caption,
};
request.fields.addAll(fields);
// multipart that takes file
var multipartFile = http.MultipartFile(
'file',
_image.readAsBytes().asStream(),
_image.lengthSync(),
filename: _image.path.split('/').last,
contentType: MediaType('image', 'jpeg'),
);
// add file to multipart
request.files.add(multipartFile);
print(request.toString());
// send
var response = await request.send();
print(response.statusCode);
// listen for response
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
I have tried uploading images with the above code as well. But this returns me the error saying "image":["No file was submitted."]

Flutter Dio add MultipartFile object to Map dynamicaly

I have custom data:
File avatar = File('path/to/file');
Map<String, dynamic> data = {
'name': 'John',
'avatar': avatar
}
How I can send this my data as FormData object to server?
I tried create object of MultipartFile class by looping my data but in my case sending file path as string instance of file. Here is my code:
data.forEach((key, value) {
if (value is File) {
String fileName = value.path.split('/').last;
data.update(key, (value) async {
return await MultipartFile.fromFile(value.path, filename: fileName);
});
}
});
FormData formData = FormData.fromMap(data);
var response = await dio.post("/send", data: formData);
But using Dio I can upload file something like this:
FormData formData = FormData.fromMap({
"name": "wendux",
"age": 25,
"file": await MultipartFile.fromFile(file.path,filename: fileName)
});
Why I can't dynamically add MultipartFile to my Map ?
You are not awaiting for your data
await Future.wait(data.map((k, v){
if(v is File){
v = await MultipartFile.fromFile(value.path, filename: fileName);
}
return MapEntry(k, v);
}));
Please look into My async call is returning before list is populated in forEach loop
You can send it without dio. Here I write the whole code including the libraries and response.Please test the below code becuase in my case dio is not working and your case is very similar to my case.
Just send it with simple http request
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart';
import 'package:mime/mime.dart';
Map<String, String> headers = {
'Content-Type': 'multipart/form-data',
};
Map jsonMap = {
"name": "wendux",
"age": 25,
};
String imagePath, // add the image path in varible
var request = http.MultipartRequest('POST', Uri.parse(url));
request.headers.addAll(headers);
request.files.add(
http.MultipartFile.fromBytes(
'orderStatusUpdate',
utf8.encode(json.encode(jsonMap)),
contentType: MediaType(
'application',
'json',
{'charset': 'utf-8'},
),
),
);
if (imagePath != null) {
final mimeTypeData = lookupMimeType(imagePath).split('/');
final file = await http.MultipartFile.fromPath('images', imagePath,
contentType: MediaType(mimeTypeData[0], mimeTypeData[1]));
print((mimeTypeData[0].toString())); // tells picture or not
print((mimeTypeData[1].toString())); // return extention
request.files.add(file);
}
http.StreamedResponse streamedResponse = await request.send();
var response = await http.Response.fromStream(streamedResponse);
print(response.statusCode);
print(response.body);

How to upload multiple images/files in Flutter using Dio?

I have been trying to upload multiple images/files to the backend in Flutter. I am using Dio.
So far, I have not been able to do so.
I have been able to do so using postman. This is the form-data
This is my code:
Future<dynamic> fileUpload(List<String> filepath, String url) async {
var token = await storage.getToken();
var idToken = await storage.getIdToken();
Dio dio = Dio();
List uploadList = [];
for (var file in filepath) {
var multipartFile = await MultipartFile.fromFile(
file
);
uploadList.add(multipartFile);
}
FormData formData = FormData.fromMap({"assignment": uploadList});
var response = await dio.post(APIURL.baseUrl + url,
data: formData,
options: Options(headers: {
HttpHeaders.authorizationHeader: "Bearer $token",
'idToken': idToken,
}));
return response;
}
Can somebody please help.
Turns out there are two ways to add multiple files to FormData. The following approach worked
var formData = FormData();
for (var file in filepath) {
formData.files.addAll([
MapEntry("assignment", await MultipartFile.fromFile(file)),
]);
}
final httpDio = Dio();
final formData = dio.FormData.fromMap({
"data": "{}",
"File": await dio.MultipartFile.fromFile(
filePath,
filename: filePath.toString().split("/").last,
contentType: MediaType('image', 'jpg'),
),
"type": "image/jpg"
});
final dio.Response response = await httpDio.post(
Strings.baseUrl +"/"+ Strings.documentUpload,
data: formData,
options: dio.Options(
headers: {
"RequestVerificationToken": box.read(Keys.token),
"Content-Type": "multipart/form-data"
}
)
);
This works as well:
var formData = FormData();
for (var file in filepath) {
formData.files.add(MapEntry("assignment",
MultipartFile.fromFileSync(file)));
}

Issues sending multiple images on Flutter using Multipart and Dio

I'm trying to send multiple files that came from Multi Image Picker pluggin on Flutter to my server, for this I'm trying to use Dio to send it. But the Multipart tag isn't uploading the files too. How to proceed?
Future<Response> _uploadFile() async {
var catUpload = jsonEncode(incluirCategoriasParaUpload());
final FormData formData = FormData.fromMap({
"action": 'add_Anuncio',
"filial_id": "1",
"titulo": tituloControler.text,
"descricao": descricaoControler.text,
"categorias": catUpload
});
for (var val in listaImagensParaUpload) {
ByteData byteData = await val.getByteData();
Uint8List pngBytes = byteData.buffer.asUint8List();
formData.files.add(
MapEntry("arquivos",
await MultipartFile.fromBytes(pngBytes, filename: "teste")
)
);
}
Dio dio = new Dio();
dio.interceptors.add(alice.getDioInterceptor());
return await dio
.post(URL_WS + WS_PAGE,
data: formData,
options: Options(method: 'POST', responseType: ResponseType.json))
.timeout(Duration(seconds: 2000));
// .catchError(dioError);
}
You must declare as toList() this for loop.
Here is an example how to make it.
formData = FormData.fromMap({
'id': '1',
'title': 'myTitle',
'files': [
for (var file in listFiles)
{await MultipartFile.fromFile(item.path, filename: 'fileName')}
.toList()
]
});
I am usign Dio library working with MultiPartFile.
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);

flutter dio upload files [pdf/ docs]

I am trying to upload files using dio package in my flutter application. I am sending my files through formdata. Here is my implementation:
Future<FormData> formData1() async {
return FormData.fromMap({
"title": "from app2",
"description": "app upload test",
"files": [
for (var i = 0; i < pathNames.length; i++)
await MultipartFile.fromFile(pathNames[i],
filename: fileNames[i])
]
});
}
Here is how I am sending my files.
_sendToServer() async {
Dio dio = Dio(
BaseOptions(
contentType: 'multipart/form-data',
headers: {
"Authorization": "$token",
},
),
);
dio.interceptors.add(
LogInterceptor(requestBody: true, request: true, responseBody: true));
FormData formData = await formData1();
try {
var response = await dio.post("http://url/api/upload",
data: formData, onSendProgress: (int send, int total) {
print((send / total) * 100);
});
print(response);
} on DioError catch (e) {
if (e.response != null) {
print(e.response.data);
print(e.response.headers);
print(e.response.request);
} else {
print(e.request.headers);
print(e.message);
}
}
}
The other fields in formdata are sent to the server but not the multipartfile. When I try and do the same from postman form-data, it uploads correctly. Am I doing something wrong here?
If you want to upload the file you can convert multipart array before calling API function because even if you put await in form data dio response will not wait for formdata object or you can use MultipartFile.fromFileSync() to get rid of await.
Let me show you in a simple way using my example. try to understand.
Multipart conversion
List multipartArray = [];
for (var i = 0; i < pathNames.length; i++){
multipartArray.add(MultipartFile.fromFileSync(pathNames[i], filename:
basename(pathNames[i])));
}
Api side
static Future<Response> createPostApi(multipartArray) async {
var uri = Uri.parse('http://your_base_url/post');
return await Dio()
.post('$uri',
data: FormData.fromMap({
"title": "from app2",
"description": "app upload test",
"files": multipartArray
}))
.catchError((e) {
print(e.response.data);
print(e.response.headers);
print(e.response.request);
});
}
Here is my code where I used file_picker flutter library and MediaType('application', 'pdf') to ensure that the content passed to the API was indeed a .pdf file.
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:http_parser/http_parser.dart';
static Future<dynamic> uploadfile(int userid, File file, String token) async {
var fileName = file.path.split('/').last;
print(fileName);
var formData = FormData.fromMap({
'title': 'Upload Dokumen',
'uploaded_file': await MultipartFile.fromFile(file.path,
filename: fileName, contentType: MediaType('application', 'pdf')),
"type": "application/pdf"
});
var response = await Dio().post('${urlapi}request/',
options: Options(
contentType: 'multipart/form-data',
headers: {HttpHeaders.authorizationHeader: 'Token $token'}),
data: formData);
print(response);
return response;
}
The file picker:
FilePickerResult? result = await FilePicker.platform.pickFiles();
if (result != null) {
File file = File(result.files.single.path ??'file.pdf');
BlocProvider.of<UploadCubit>(context)
.uploadFile(statelogin.user.id, file,
statelogin.user.token);
}
Change formdata with following rest is fine
import 'package:path/path.dart' as pathManager;
import 'package:mime/mime.dart' as mimeManager;
FormData formdata = FormData();
formdata.add(
"files",
[UploadFileInfo(img, pathManager.basename(img.path),
contentType:
ContentType.parse(mimeManager.lookupMimeType(img.path)))]);
// here attachmentFile is File instance, which is set by File Picker
Map<String, dynamic> _documentFormData = {};
if (attachmentFile != null) {
_documentFormData['document_file'] = MultipartFile.fromFileSync(attachmentFile.path);
}
FormData formData = FormData.fromMap(_documentFormData);
try {
var response = await dio.post("http://url/api/upload",
data: formData, onSendProgress: (int send, int total) {
print((send / total) * 100);
});
print(response);
} on DioError catch (e) {
if (e.response != null) {
print(e.response.data);
print(e.response.headers);
print(e.response.request);
} else {
print(e.request.headers);
print(e.message);
}
}
Here you can use MultipartRequest class without using any of library to upload any kind of files using restAPI.
void uploadFile(File file) async {
// string to uri
var uri = Uri.parse("enter here upload URL");
// create multipart request
var request = new http.MultipartRequest("POST", uri);
// if you need more parameters to parse, add those like this. i added "user_id". here this "user_id" is a key of the API request
request.fields["user_id"] = "text";
// multipart that takes file.. here this "idDocumentOne_1" is a key of the API request
MultipartFile multipartFile = await http.MultipartFile.fromPath(
'idDocumentOne_1',
file.path
);
// add file to multipart
request.files.add(multipartFile);
// send request to upload file
await request.send().then((response) async {
// listen for response
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}).catchError((e) {
print(e);
});
}
I used file picker to pick file. Here is the codes for pick file.
Future getPdfAndUpload(int position) async {
File file = await FilePicker.getFile(
type: FileType.custom,
allowedExtensions: ['pdf','docx'],
);
if(file != null) {
setState(() {
file1 = file; //file1 is a global variable which i created
});
}
}
here file_picker flutter library.