Cannot upload image using dio post request - flutter

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."]

Related

Flutter http sending list value in the body in a post multipart request

I am trying to send a multipart post request to upload images and sending some other data in flutter with a body looks like this
bodyMap = {
'type' : 'text',
'content': [
{
'type': image'
'identifier: '1234'
}
]
};
However when I'm trying to add it to the request like this
var request = http.MultipartRequest('POST', Uri.parse(url));
request.fields.addAll(bodyMap);
it refuses to add it as it only accepts Map<String, String>
how to solve this problem?
I have found that Dio Package allows you to post a map of type Map<String,Dynamic> with multipart post request, for example:
var formData = FormData.fromMap({
'name': 'wendux',
'age': 25,
'file': await MultipartFile.fromFile('./text.txt', filename: 'upload.txt'),
'files': [
await MultipartFile.fromFile('./text1.txt', filename: 'text1.txt'),
await MultipartFile.fromFile('./text2.txt', filename: 'text2.txt'),
]
});
var response = await dio.post('/info', data: formData);

send image and text at the same time flutter

I want to upload image and other types of data like string and integer with the HTTP post method at the same time. but i got error code said that json cant encode image file, i have this code on flutter :
static Future<ApiReturnValue<Asset>> addAsset(Asset asset, File imageFile,
{http.Client client}) async {
client ??= http.Client();
String url = baseUrl + 'asset';
var uri = Uri.parse(url);
var response = await client.post(
uri,
headers: {
"Content-type": "application/json",
"Authorization": "Bearer ${User.token}"
},
body: jsonEncode(
<String, dynamic>{
"name": asset.name,
"condition": asset.condition,
"purchase_date": asset.purchaseDate,
"price": asset.price,
"location": asset.location,
"description": asset.description,
"image": imageFile,
},
),
);
if (response.statusCode != 200) {
return ApiReturnValue(message: "Add item failed, please try again");
}
var data = jsonDecode(response.body);
Asset value = Asset.fromJson(data['data']['asset']);
return ApiReturnValue(value: value);
}
is that any way that I can send image and text on HTTP post request at the same time without separating the image using multipart request?
To include an image in the request body for POST, normally you have to convert it into a multipart file, then include it in the body as formdata. This required the server to expect the multipart file within the formdata itself when receive the image from client.
I'd like to recommend this package name dio for you. It supports MultipartFile, FormData and other powerful helper classes.
Here's an example:
static Future<bool> sendImage(String imagePath) async {
try {
final content = MultipartFile.fromFile(imagePath);
final contentType = 'multipart/form-data';
final Response response = await dio.post('$BASE_URL/$images',
data: FormData.fromMap({'file': content}),
options: Options(contentType: contentType));
if (response.statusCode == 200) {
return true;
}
return false;
} catch (error) {
return null;
}
}
You can read more on the FormData here
You can have your asset data in the request header:
var response = await client.post(
uri,
headers: {
"Content-type": "application/json",
"Authorization": "Bearer ${User.token}",
"asset-data": jsonEncode(
<String, dynamic>{
"name": asset.name,
"condition": asset.condition,
"purchase_date": asset.purchaseDate,
"price": asset.price,
"location": asset.location,
"description": asset.description
},
),
},
body: imageFile.readAsBytesSync(),
);
This will need you to modify your server-side code to read from the header.

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 send an object in formdata flutter

I am currently working on a mobile app and I am stuck in this for days now. I have been trying to send a post request to create an object "Leave" as represents the code below. The request body is formData with a key 'leave' and value 'jsonObject'.I've tried a lot of methods and it has a relation with 'Content-type'I suppose. If i change it to 'multipart/form-data' the response becomes 500 and if it is 'application/json' i always get 415 unsupported mediaType. This is my code using dio package, any advice would be helpful guys, thank u on advance.Postman request works fine
Future createLeave() async {
var leave = Conge(
dateDemand: DateTime.now(),
dateEnd: DateTime.now().add(Duration(days: 3)),
dateStart: DateTime.now().add(Duration(days: 1)),
type: "CSS",
endDateDaySlot: "X",
startDateDaySlot: "X",
);
Map<String, String> heads = {
"X-Auth-Token": UserPreferences().token,
"Content-type": 'application/json',
"accept": "application/json"
};
FormData formData = FormData.fromMap({"leave": leave.toJson()});
var dio = Dio();
try {
Response response = await dio.post(API + '/leave/add',
data: formData,
options:
Options(headers: heads, contentType: Headers.jsonContentType));
} on Exception catch (e) {
print(e);
}
}
I have also tried to use MultiPartRequest but i always get 400 as a response, the request sent by the client was syntactically incorrect here is my code could anyone help me with this please
Future create(Conge leave) async {
String url = API + "/leave/add";
var uri = Uri.parse(url);
var request = new http.MultipartRequest("POST", uri);
Map<String, String> heads = {
"X-Auth-Token": UserPreferences().token,
"Content-type": 'application/json',
};
request.headers.addAll(heads);
request.fields['leave'] = json.encode(leave.toJson());
var response = await request.send();
print(response.statusCode);
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}
Please try to disable the firewall of windows, if it works then make an exception for it in the firewall.

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)));
}