How can i send the Map Object in multipart request in flutter - flutter

Here I am trying to send the Object Map in the multipart request but my request is going as a string, not in JSON format please suggest me to do correct request. Thanks in advance.
I have tried the multipart request but my request should be in correct form..
var getApiUrl = 'http://malik-env-test.ap-south-1.elasticbeanstalk.com/webapi/post/create';
Map userData = {
"creator": {
"creatorId": "298",
"createDate": "2018-12-21 20:44:45.8"
},
"info": "$campusInfo",
"title": "$eventName",
"postCampusId": "5642"
};
Uri uri = Uri.parse(getApiUrl);
http.MultipartRequest request = new http.MultipartRequest('POST', uri);
request.fields['creator'] = userData['creator'];
request.fields['info'] = '$campusInfo';
request.fields['title'] = '$eventName';
request.fields['postCampusId'] = '5642';
request.files.add(await http.MultipartFile.fromPath('image_file1', imagePath, contentType: new MediaType('application', 'x-tar')));
// var body = json.encode(request);
print(request);
http.StreamedResponse response = await request.send();
String jsonData = response.toString();
print(jsonData);ddd

Try:
request.fields['userData'] = json.encode(userData);
You need to find out from the API spec or server owner what field name to use for the json. I've assumed userData.
If you want control over the media type, encoding, etc, add it as a file like this:
request.files.add(
http.MultipartFile.fromBytes(
'the_form_field name',
utf8.encode(json.encode(userData)),
contentType: MediaType(
'application',
'json',
{'charset': 'utf-8'},
),
),
);

I think, the easiest way to add object fields is using brackets like this ;
request.fields['creator[creatorId]'] = '$creatorId';
request.fields['creator[createDate]'] = '$createDate';
request.fields['title'] = '$eventName';
request.fields['postCampusId'] = '5642';
So, for the fields inside another you need to put the object name first then add to fields name inside brackets.
this should work just fine.

var userData = json.encode({
"creator": {
"creatorId": "298",
"createDate": "2018-12-21 20:44:45.8"
},
"info": "$campusInfo",
"title": "$eventName",
"postCampusId": "5642"
});
var client = http.Client();
client
.post('https://'+ url ,
headers: {
'content-type': 'application/json',
},
body: userData )

Related

Dio Error : Http Status Error Code [ 405 ] Flutter

I am getting HTTP status error code 405 on sending post requests from the real devices but it's working inside the postman.
The URL is: https://amapp.adtestbed.com/api/post-survey
The following is the form data I am using
FormData formData = FormData.fromMap({
'user_id': id,
'is_collection':
jobDetailsResponseModel.jobData.jobStatus == '8' ? 1 : 0,
'job_id': jobDetailsResponseModel.jobData.id,
'job_no': bookingIdController.text.toString(),
'sender_name': senderNameController.text.toString(),
'reciever_name': recieverNameController.text.toString(),
'sender_phone': senderPhoneController.text.toString(),
'reciever_phone': recieverPhoneController.text.toString(),
'sender_address': senderAddressController.text.toString(),
'reciever_address': recieverAddressController.text.toString(),
'sender_signature_data':
"data:image/jpeg;base64," + base64Imagesendersign,
'receiver_signature_data':
"data:image/jpeg;base64," + base64Imagerecieversign,
'location': currentLocation,
'images[]': uploadimages,
'maked[]': makedlist,
'model[]': modallist,
'rego[]': regolist,
'speedo[]': speedolist,
'is_drivable[]': isdrivablelist,
'goods_inside[]': goodsinsidelist,
'external_condition[]': externalconditionlist,
'interior_condition[]': internalconditionlist,
'survey_image[]': surveyimagelist,
'comments[]': commentlist
});
Here images field is a multipart form list.
And doing requests as follows
final response = await Dio().request(
'https://amapp.adtestbed.com/api/post-survey',
data: formData,
options: Options(
headers: {
"Accept": "application/json",
},
method: 'POST',
),
);
also used the following code to check but still not working
final response = await Dio().post(
'https://amapp.adtestbed.com/api/post-survey',
data: formData,
options: Options(
// headers: {
// // "Accept": "application/json",
// // 'Content-Type': 'application/x-www-form-urlencoded'
// },
method: 'POST',
),
);
When I am sending the form without an images field then it's submitting perfectly and giving 200 status but when I am sending it's with an images field that contains a multipart form list then it's returning 405 status code. End giving the error like the get method not supported only support post method. I also checked the backend code but no error from that's side because it's giving an error before sending the request. I also checked if there were some null data that created errors but not a single field is null.
But when I am doing both cases in postman then it's working fine.
This is the postman link:
https://drive.google.com/file/d/1hTmDC2aQ7vTMxSnzwaeRqd9gv7UbPWhR/view?usp=sharing
These are some images of the postman
https://stackoverflow.com/a/64235806/11623001
Check this out I had a similar issue too before, and I also noticed that you are not adding your authorization token to your header which may explain why you are getting 405 which would mean you can't have access.
I tried to recreate your issue on my end but the authorization token is expired, I'm getting a 401, but here is the code:
void postSome() async {
String base64 =
//This base64 is shortened "data:image/png;base64,...+WZm/et53efvWO6Tuc6rH7kUXy1lxs+/61t7dMg6VAvURAAAAQHMQogDAbE6dlLXtft/F3cuvkJNbetbn7VWrpUUX+mvEtqdHvgAAAABoOf8P3x1uDPELl4UAAAAASUVORK5CYII=";
FormData formData = FormData.fromMap({
'user_id': 139,
'is_collection': "1" == '8' ? 1 : 0,
'job_id': "248",
'job_no': "60036JL#1",
'sender_name': "test",
'reciever_name': "test",
'sender_phone': "1234567890",
'reciever_phone': "1234567890",
'sender_address': "test",
'reciever_address': "test",
'sender_signature_data':
base64,
'receiver_signature_data': base64,
'location': "32, Gopal Nagar, Om Nagar, Gopal Nagar Society, Parvat Patiya, Surat, Gujarat 395010, India\n",
'images[]': "/D:/App/Logicwind/GitLAb/whiteboard-digitization/test_images/w11.jpg",
'maked[]': "test",
'model[]': "test",
'rego[]': "test",
'speedo[]': "123",
'is_drivable[]': "1",
'goods_inside[]': "1",
'external_condition[]': "3",
'interior_condition[]': "3",
'survey_image[]': base64,
'comments[]': "test"
});
final response = await Dio().request(
'https://amapp.adtestbed.com/api/post-survey',
data: formData,
options: Options(
headers: {
'Accept': "application/json",
'Authorization': 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIzIiwianRpIjoiNTlkNzNlZjE4YzcxNGJjMWM1ZjE0ZGQxOWE1OWZmNmQ1YjVhNDViNDIwNzlkODY4ZmJkOGRmNjJlOGM4MDQzNmVjYmIxZjc4MjM5MmZiOGIiLCJpYXQiOjE2MjgxNzY5NTAsIm5iZiI6MTYyODE3Njk1MCwiZXhwIjoxNjU5NzEyOTUwLCJzdWIiOiI0NiIsInNjb3BlcyI6W119.lfnzUvq_LwYtBUQ-t6S_mKXEoM6er6ZzCuTUoHnqz9wwrdLOcu6x9CEixqMRvI-RWtSoiMO5KCYZsgagayGW5slYk6zAAa0V5fCjkRipqqus6mXe6nowtcXs_2V9ucjVoH4Evkb9lFBlE1rlpxKgcGXTcx4UgQs8kjJ5Wm4A8omedza_hUQPN9KUAfhhBDeL9hq-DkC7QbLu_YxnG5g-AETKhbJu8T4HWKqkh9NKGbNlvs1oi_nD81F1w8uSteY-UOgDJyUoGJxzoD6xmEv3J4mkrdr1ZbG88EzTyk3zngwBp9eWcLHhMS2psxArOnOnWusweJJ5uZiWiu2VIL7fWmV5b6G4OCvvkba5eXmw8iAvACACuCGQtOcGdN_euUgyfM9z9a8QbK8M2I-ux4GGY0ejCamFEJZCTwyBCxmLIrP4XjQoeL71WT1YBOgSZwDjA6qrAfL_fLwbEYQYbLIF8fLUmDOWRKBIaJLSVNG2x0Gl5LLXTiTZAzRRtJlSxZ4-Vid4hQJX39lohp-47XPAxvHnNTxiLw_aAG3SruFZ_rtdX4xnNbV3hSI825CD5dBeQC5iE-hiLXDWDXelM_q2fSD1rez62XQZGp1KfvlwowxAWgIghTfSH_E52h6mdoHEo9q73UJNYDz_F9Sj8EOfY3VWtmN6HMmcs4HZht36qX4',
},
method: 'POST',
),
);
print(response.statusCode);
}
It looks like below two fields are files not a form data.
'sender_signature_data': "data:image/jpeg;base64," + base64Imagesendersign
'receiver_signature_data': "data:image/jpeg;base64," + base64Imagerecieversign
You should add those as file fields like this
"sender_signature_data": await MultipartFile.fromFile(sender_signature_path,
filename: fileName, contentType: MediaType(mimee, type))
}),
"receiver_signature_data":await MultipartFile.fromFile(reciever_signature_path,
filename: fileName, contentType: MediaType(mimee, type))
})

Post array of multipart files using HTTP package with same field name, i.e. as form data

I am trying to send multiple file in the following JSON format;
{
"product_id": 1,
"images":[ /* here is the array of images picked */ ]
}
Using dio, there is a way to achieve this by form data
FormData.fromMap({
"product_id":product_id,
'images': [
MultipartFile.fromFileSync('./example/upload.txt', filename: 'upload.txt'),
MultipartFile.fromFileSync('./example/upload.txt', filename: 'upload.txt'),
]
});
How can I achieve this using HTTP package?
List<http.MultipartFile> _multiFiles = [];
images.forEach((element) async {
final _part = await http.MultipartFile.fromPath(
"images",
element,
contentType: MediaType('application', '*'),
);
_multiFiles.add(_part);
});
final _request = http.MultipartRequest(
'POST',
_appUrl(_url),
)..fields['product_id'] = product.id.toString()
..files.addAll(_multipartFiles)
Using this, the images are not uploaded since the backend requires key named "images", which is an array of files,how do I achieve this.

Http Post is working in Postman, but not Flutter

edit: I found the solution and answered the question.
I'm trying POST to Instagram's API in my app. The POST works fine in Postman, but in my flutter code I always get a error response: {error_type: OAuthException, code: 400, error_message: Invalid platform app} . I must be doing something wrong in my flutter POST but I can't figure out what.
Here is my Postman POST (that works every time) along with the correct body response:
And here is my Dart/Flutter code that gives me the error:
var clientID = '708XXXXXXXX';
var clientSecret = '37520XXXXXXXXXXXXX';
var grantType = 'authorization_code';
var rediUrl = 'https://httpstat.us/200';
var urlTwo = 'https://api.instagram.com/oauth/access_token';
var body = json.encode({
'client_id': clientID,
'client_secret': clientSecret,
'grant_type': grantType,
'redirect_uri': rediUrl,
'code': _accessCode
});
print('Body: $body');
var response = await http.post(urlTwo,
headers: {
'Accept': '*/*',
'Content-Type': 'application/json',
},
body: body,
);
print(json.decode(response.body));
I read about the error on a different thread and they say to post as x-www-formurlencoded.. When I switch the Content-Type to this, I get the same error.
The error I get in Flutter:
{error_type: OAuthException, code: 400, error_message: Invalid platform app}
I triple checked and I am using all the same value in Postman and Flutter. I've tried the values as Strings and numbers.
When I print body:
Body: {"client_id":"70000edited","client_secret":"37520634edited","grant_type":"authorization_code","redirect_uri":"https://httpstat.us/200","code":"AQCs-H3cIU0aF1o2KkltLuTmVMmJ-WJnZIhb9ryMqYedited"}
try this once
final response = await http.post(urlTwo,
body: body,
headers: {
"Accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded"
},
encoding: Encoding.getByName("utf-8"));
I've finally got it working using a Map. Which is weird because other attempts I also used a map (I've been trying numerous stack overflow answers). Anyways, here is the working code I used:
var urlTwo = 'https://api.instagram.com/oauth/access_token';
var clientID = '7080000';
var clientSecret = '375XXXXXX';
var grantType = 'authorization_code';
var rediUrl = 'https://httpstat.us/200';
var map = new Map<String, dynamic>();
map['client_id'] = clientID;
map['client_secret'] = clientSecret;
map['grant_type'] = grantType;
map['redirect_uri'] = rediUrl;
map['code'] = _accessCode;
http.Response response = await http.post(
urlTwo,
body: map,
);
var respData = json.decode(response.body);
print(respData);

How will i send nested Json to Rest Api in Flutter

i am trying to send json data to my rest api.
it works when my "ContactData" as just 6 items but if it more than 6 item like the way it is, my api will see it as null.
var ContactData = {
'myContactData1': myContactDataItem1,
'myContactData2': myContactDataItem2,
'myContactData3': myContactDataItem3,
'myContactData4': myContactDataItem4,
'myContactData5': myContactDataItem5,
'myContactData6': myContactDataItem6,
'myContactData7': myContactDataItem7,
'myContactData8': myContactDataItem8,
'myContactData9': myContactDataItem9,
'myContactData10': myContactDataItem10,
'myContactData11': myContactDataItem11,
'myContactData12': myContactDataItem12,
'myContactData13': myContactDataItem13,
'myContactData14': myContactDataItem14,
'myContactData15': myContactDataItem15,
'myContactData16': myContactDataItem16,
'myContactData17': myContactDataItem17,
'myContactData18': myContactDataItem18,
'myContactData19': myContactDataItem19,
};
if i should reduce "ContactData" to just 6 items, i will work fine
Map data = {
'contact' : ContactData,
'item1': itemdata1,
'item2': itemdata2,
'item3': itemdata3,
'item4': itemdata4,
'item5': itemdata5,
'item6': itemdata6,
'item7': itemdata7,
'item8': itemdata8,
'item9': itemdata9,
'item10': itemdata10,
'item11': itemdata11,
'item12': itemdata12,
'item13': itemdata13,
'item14': itemdata14,
'item15': itemdata15,
'item16': itemdata16,
'item17': itemdata17,
'item18': itemdata18,
'item19': itemdata19,
};
//encode Map to JSON
var dataToSend = json.encode(data);
var response = await http.post("v1/add"),
headers: {
"Content-Type": "application/json; charset=UTF-8",
"securedData": ServiceConnector.securedData,
},
body: dataToSend);

Flutter Dart HTTP POST request body is empty on server side

I am working on a Flutter tablet app. Once one input field is inputted, I am trying to send a post request to the server. Following is the method I am invoking for this:
Future < http.Response > _postRequest() async {
print(globals.novaCoord.toString() + ' XYZXYZXYZXYZXYZ');
var url = globals.URL + 'api/nova_position';
Map data = {
'id_nova': '1',
'position.x': '1',
'position.y': '1',
'position.z': '1',
'position.pitch': '1',
'position.yaw': '1',
'position.roll': '1',
};
//encode Map to JSON
var body = json.encode(data);
http.Response response = await http.post(url,
headers: {
"Content-Type": "application/json"
},
body: body
);
print("${response.statusCode}");
print("${response.body}");
return response;
}
And on the NodeJs server side I have this:
app.post('/api/nova_position/', async (req,res) => {
console.log("NOVA POSITION");
console.log(req.body.id_nova);
const id_nova = req.body.id_nova;
const x = req.body.position.x;
const y = req.body.position.y;
const z = req.body.position.z;
const pitch = req.body.position.pitch;
const yaw = req.body.position.yaw;
const roll = req.body.position.roll;
const position = await db.db.create_position(id_nova,x,y,z,pitch,yaw,roll);
});
However, on the server-side, I am receiving an empty "body" for the request I sent and I receive the following error:
(node:23939) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'x' of undefined
I need help at this point. I appreciate any help and guidance.
Sending Map<String,dynamic> with http.post won't send your data properly.
To solve this, change the content-type of the header to:
Map<String, String> customHeaders = {
...
"content-type": "application/json"
...
};
Then, you can use http.post as follows:
http.post(url, headers: customHeaders, body);
You have to jsonEncode before pushing into Post request
Like
String bodyF = jsonEncode(body);
And i hope you will get your solution.
The solution I have found was simply to add Content-Length : x to your header, with x being the size of your json body.