Can't upload multiple image in flutter POST request - flutter

I'm trying to upload multiple images in backend.
I got this response when I'm trying to print files:
[Instance of 'MultipartFile', Instance of 'MultipartFile', Instance of 'MultipartFile']
but at a server side I got null array {}. This is my method. I'm using http for api communication.
Future<Map<String, dynamic>> postWithMultiImage(
String _url,
Map<String, String> _headers,
Map<String, String> _params,
String _imageKey,
List _imageFile) async {
if (_headers != null) {
print('_headers => $_headers');
}
print('_params => $_params');
print('_url => $_url');
var request = http.MultipartRequest("POST", Uri.parse(BASE_URL + _url));
if (_headers != null) {
request.headers.addAll(_headers);
}
if (_params != null) {
request.fields.addAll(_params);
}
if (_imageFile != null) {
for (int i = 0; i < _imageFile.length; i++) {
final _type = lookupMimeType(_imageFile[i]);
final _name =
'${DateTime.now().toIso8601String()}.${_type.split('/').last}';
final _partFile = http.MultipartFile(
_imageKey,
File(_imageFile[i]).openRead(),
File(_imageFile[i]).lengthSync(),
filename: _name);
request.files.add(_partFile);
}
print('request files: ${request.files}');
}
var response = await request.send();
final code = response.statusCode;
print('response code => $code');
final responseBody = await http.Response.fromStream(response);
final body = responseBody.body;
final jsonBody = json.decode(body);
Map<String, dynamic> _resDic;
if (code == 200) {
_resDic = Map<String, dynamic>.from(jsonBody);
_resDic[STATUS] = _resDic[SUCCESS] == 1;
} else {
_resDic = Map<String, dynamic>();
_resDic[STATUS] = false;
_resDic[IS_TOKEN_EXPIRED] = 0;
_resDic[MESSAGE] = jsonBody[MESSAGE] != null
? jsonBody[MESSAGE]
: 'Something went wrong';
}
_resDic[HTTP_CODE] = code;
return _resDic;
}
Thanks in advance.

You can try >>THIS<<

Related

Searching through List<HashMap<String, dynamic>> and return if it contains value flutter

Below is how i am fetching my data
static Future<List<Item>> fetchItems(String query) async {
try {
final response = await http.get(
Uri.parse(
"https://api.json-generator.com/templates/ueOoUwh5r44G/data"),
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer tltsp6dmnbif01jy9xfo9ssn4620u89xhuwcm5t3",
}) /*.timeout(const Duration(seconds: Config.responseTimeOutInSeconds))*/;
final List<Item> itemsList;
if (response.statusCode == 200) {
itemsList = json
.decode(response.body)
.map<Item>((json) => Item.fromJson(json))
.where((item) {
final idLower = item.id.toLowerCase();
final titleLower = item.title.toLowerCase();
final subTitleLower = item.subTitle.toLowerCase();
final searchLower = query.toLowerCase();
return idLower.contains(searchLower) ||
titleLower.contains(searchLower) ||
subTitleLower.contains(searchLower);
}).toList();
} else if (response.statusCode == 401) {
itemsList = [];
} else {
itemsList = [];
}
return itemsList;
} catch (e) {
if (kDebugMode) {
Logger().wtf(
"FetchItemsException $e \n\nResponseStatusCode ${statusCode!}");
}
rethrow;
}
}
The above code is when i am using a class of Item. The issues that i am having is i have switched to load and populate the data using List<HashMap<String, dynamic>> instead of Item class
The code above is working fine if i am using List but fails when i am using List<HashMap<String, dynamic>>
I am going to highlight the section that is failing. Below is how i was checking if the following variables idLower, titleLower, subTitleLower contains what is in the search query and return the Item. Below is the code of how i was doing that
if (response.statusCode == 200) {
itemsList = json
.decode(response.body)
.map<Item>((json) => Item.fromJson(json))
.where((item) {
final idLower = item.id.toLowerCase();
final titleLower = item.title.toLowerCase();
final subTitleLower = item.subTitle.toLowerCase();
final searchLower = query.toLowerCase();
return idLower.contains(searchLower) ||
titleLower.contains(searchLower) ||
subTitleLower.contains(searchLower);
}).toList();
}
Below is how i am fetching using List<HashMap<String, dynamic>>
static Future<List<HashMap<String, dynamic>>> fetchLists(
String url, String query) async {
try {
final response = await http.get(Uri.parse(url), headers: {
"Content-Type": "application/json",
"Authorization": "Bearer tltsp6dmnbif01jy9xfo9ssn4620u89xhuwcm5t3",
}).timeout(const Duration(seconds: Config.responseTimeOutInSeconds));
statusCode = response.statusCode;
final List<HashMap<String, dynamic>> responseList;
if (response.statusCode == 200) {
responseList = json
.decode(response.body)
.map<HashMap<String, dynamic>>(
(e) => HashMap<String, dynamic>.from(e))
.where((mapItem) {
final idLower = mapItem["id"].toLowerCase();
final titleLower = mapItem["title"].toLowerCase();
final subTitleLower = mapItem["subTitle"].subTitle.toLowerCase();
final searchLower = query.toLowerCase();
return idLower.contains(searchLower) ||
titleLower.contains(searchLower) ||
subTitleLower.contains(searchLower);
}).toList();
} else if (response.statusCode == 401) {
responseList = [];
} else {
responseList = [];
}
return responseList;
} catch (e) {
if (kDebugMode) {
Logger().wtf(
"FetchUsersUsingListOfStringObjectHashMapException $e \n\nResponseStatusCode ${statusCode!}");
}
rethrow;
}
}
And below is how i have tried to check if the items in the HashMap is contained in the query but its not working
if (response.statusCode == 200) {
responseList = json
.decode(response.body)
.map<HashMap<String, dynamic>>(
(e) => HashMap<String, dynamic>.from(e))
.where((mapItem) {
final idLower = mapItem["id"].toLowerCase();
final titleLower = mapItem["title"].toLowerCase();
final subTitleLower = mapItem["subTitle"].subTitle.toLowerCase();
final searchLower = query.toLowerCase();
return idLower.contains(searchLower) ||
titleLower.contains(searchLower) ||
subTitleLower.contains(searchLower);
}).toList();
}

Flutter & Firebase - Get a specific field from document

I have been trying to get a specific field from a specific document. I need token for toWho. But I always got null. How do I fix this?
Main Code is
Future<String> getUserToken(String toWho) async {
DocumentSnapshot _doc = await FirebaseFirestore.instance.doc("tokens/" + toWho).get();
if (_doc != null) {
Map<String, dynamic> _data = _doc.data();
return _data["token"];
} else {
return null;
}
}
in Repository
Future<bool> sendMessage(
MessageModel sendingMessage, UserModel currentUser) async {
if (appMode == AppMode.DEBUG) {
return true;
} else {
var _writePrcs = await _firestoreDBService.saveMessage(sendingMessage);
if (_writePrcs) {
var _token = "";
if (_userToken.containsKey(sendingMessage.toWho)) {
_token = _userToken[sendingMessage.toWho];
print("Token lokalden geldi.");
} else {
_token = await _firestoreDBService.getUserToken(sendingMessage.toWho);
_userToken[sendingMessage.toWho] = _token;
print("Token veritabanından geldi.");
}
Thanks for your help from now on
Try ...........
Future<String> getUserToken(String toWho) async {
DocumentSnapshot _doc = await
FirebaseFirestore.instance.collection("tokens/groupChatId/message").doc(toWho).get();
if (_doc != null) {
Map<String, dynamic> _data = _doc.data();
return _data["token"];
} else {
return null;
}
}

how to convert excel sheet into json in flutter

how to convert excel sheet into json in flutter.
I have a excel sheet of students names and classes and i want to convert it to json to make it easy to run the app or another way to upload date to firestore.
Future<String> excelToJson() async {
var file = await FilePicker.getFilePath(
type: FileType.custom, allowedExtensions: ['xlsx', 'csv', 'xls']);
var bytes = File(file).readAsBytesSync();
var excel = Excel.decodeBytes(bytes);
int i = 0;
List<dynamic> keys = new List<dynamic>();
List<Map<String, dynamic>> json = new List<Map<String, dynamic>>();
for (var table in excel.tables.keys) {
for (var row in excel.tables[table].rows) {
if (i == 0) {
keys = row;
i++;
} else {
Map<String, dynamic> temp = Map<String, dynamic>();
int j = 0;
String tk = '';
for (var key in keys) {
tk = "\u201C" + key + "\u201D";
temp[tk] = (row[j].runtimeType==String)?"\u201C" + row[j].toString() + "\u201D":row[j];
j++;
}
json.add(temp);
}
}
}
print(json.length);
String fullJson = json.toString().substring(1, json.toString().length - 1);
return fullJson;}
I want to learn how to use this script in my application or another way is more easy and simple
Thanks
Use this methods:
Future<void> excelToJson(String fileName, String fileDirectory,GlobalKey<ScaffoldState> scaffoldKey) async {
ByteData data = await rootBundle.load(fileDirectory);
var bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
var excel = Excel.decodeBytes(bytes);
int i = 0;
List<dynamic> keys = new List<dynamic>();
List<Map<String, dynamic>> json = new List<Map<String, dynamic>>();
for (var table in excel.tables.keys) {
for (var row in excel.tables[table].rows) {
if (i == 0) {
keys = row;
i++;
} else {
Map<String, dynamic> temp = Map<String, dynamic>();
int j = 0;
String tk = '';
for (var key in keys) {
tk = '"' + key + '"';
temp[tk] = (row[j].runtimeType == String)
? '"' + row[j].toString() + '"'
: row[j];
j++;
}
json.add(temp);
}
}
}
print(json.length);
String fullJson = json.toString().substring(1, json
.toString()
.length - 1);
fullJson = '{ "DATA" : [$fullJson]}';
final directory = await getExternalStorageDirectory();
File file = await File('${directory.path}/$fileName.json').create();
await file.writeAsString(fullJson).then((value) =>
scaffoldKey.currentState
.showSnackBar(SnackBar(content: Text("Completed")))
);
print(file.exists().toString());
}
Future<void> jsonToExcel(String fileName, String fileDirectory,GlobalKey<ScaffoldState> scaffoldKey) async{
String jsonString = await rootBundle.loadString(fileDirectory);
List<dynamic> jsonResult = jsonDecode(jsonString)["DATA"];
var excel = Excel.createExcel();
Sheet sheetObject = excel['Sheet1'];
Map<String,dynamic> result = jsonResult[0];
sheetObject.appendRow(result.keys.toList());
for(int i =0;i<jsonResult.length;i++){
Map<String,dynamic> result = jsonResult[i];
sheetObject.appendRow(result.values.toList());
}
final directory = await getExternalStorageDirectory();
excel.encode().then((onValue) {
File(("${directory.path}/$fileName.xlsx"))
..createSync(recursive: true)
..writeAsBytesSync(onValue);
scaffoldKey.currentState
.showSnackBar(SnackBar(content: Text("Completed")));
});
print(sheetObject);
}
Updated your code just a bit....
Future<String> excelToJson() async {
FilePickerResult result =await FilePicker.platform.pickFiles(type:FileType.custom,allowedExtensions: ['xls','xlsx','csv']);
if (result != null) {
File excelFile = File(result.files.single.path);}
var bytes = File(excelFilePath).readAsBytesSync();
var excel = Excel.decodeBytes(bytes);
int i = 0;
List<dynamic> keys = [];
var jsonMap = [];
for (var table in excel.tables.keys) {
dev.log(table.toString());
for (var row in excel.tables[table].rows) {
dev.log(row.toString());
if (i == 0) {
keys = row;
i++;
} else {
var temp = {};
int j = 0;
String tk = '';
for (var key in keys) {
tk = '\"${key.toString()}\"';
temp[tk] = (row[j].runtimeType == String)
? '\"${row[j].toString()}\"'
: row[j];
j++;
}
jsonMap.add(temp);
}
}
}
dev.log(
jsonMap.length.toString(),
name: 'excel to json',
);
dev.log(jsonMap.toString(), name: 'excel to json');
String fullJson =
jsonMap.toString().substring(1, jsonMap.toString().length - 1);
dev.log(
fullJson.toString(),
name: 'excel to json',
);
return fullJson;
}

Flutter generic REST API call function

I am working on first my flutter app. App required to call rest api and return back result. I am looking to create generic function to call rest api. I have written below code but I am not understating, how can I decode api response in specific model.
Future<T> apiRequest<T>(
String endPoint,
RequestMethod method, {
String body = '',
String token = '',
}) async {
http.Response resp;
final String url = LocalConstants.apiBaseUrl + endPoint;
final Map<String, String> headers = new Map<String, String>();
headers.putIfAbsent(
HttpHeaders.contentTypeHeader, () => 'application/json');
if (token != null && token.isNotEmpty) {
headers.putIfAbsent(
HttpHeaders.authorizationHeader, () => 'Bearer ' + token);
}
try {
if (method == RequestMethod.get) {
resp = await http.get(
url,
headers: headers,
);
} else if (method == RequestMethod.put) {
resp = await http.put(
url,
headers: headers,
body: body,
);
} else if (method == RequestMethod.post) {
resp = await http.post(
url,
headers: headers,
body: body,
);
} else if (method == RequestMethod.delete) {
resp = await http.delete(
url,
headers: headers,
);
}
if (resp != null && this.validateResponse(resp)) {
return json.decode(resp.body);
}
// else {
// Response resp = new Response();
// resp.respMsg = LocalConstants.genericError;
// resp.respCode = LocalConstants.resp_failure;
// Response.
// }
} on TimeoutException catch (e) {
//handleTimeout();
} on SocketException catch (e) {
print('Socket Error: $e');
//handleTimeout();
} on Error catch (e) {
print('General Error: $e');
//showError();
}
}
Below is code which I can use to call rest api
await ApiService.newInstance(context)
.apiRequest<GenericResp>('/api/people', RequestMethod.get);
Here is my GenericResp class
import 'package:project/models/Response.dart';
class GenericResp extends Response {
int id;
int otherId;
String mappingId;
GenericResp({
this.id,
this.otherId,
this.mappingId,
});
GenericResp.fromJson(Map<String, dynamic> json) {
id = json['id'];
otherId = json['other_id'];
mappingId = json['mapping_id'];
respCode = json['resp_code'];
respMsg = json['resp_msg'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = this.id;
data['other_id'] = this.otherId;
data['mapping_id'] = this.mappingId;
data['resp_code'] = this.respCode;
data['resp_msg'] = this.respMsg;
return data;
}
}
How can I decode body json.decode(resp.body); to GenericResp of type T?
You can add a generic argument that will deserialize your json data to GenericResp. Something like that:
Future<T> apiRequest<T>(
String endPoint,
RequestMethod method, T Function(Object json) fromJson, {
String body = '',
String token = '',
}) async { ... }
And after json decoding you are to use fromJson argument:
if (resp != null && this.validateResponse(resp)) {
return fromJson(json.decode(resp.body));
}
And then a call would look like this:
await ApiService.newInstance(context).apiRequest<GenericResp>('/api/people',
RequestMethod.get, (json) => GenericResp.fromJson(json));

Question mark converted to %3F in URI

I'm working on a project and I'm trying to get information from an API. When I write the link it doesn't detect the character "?" and it substitutes this char for "%3F" so I can't access to the API.
final String _charactersUrl = '/api/character/?page=2';
I get status code 500 from the API:
https://rickandmortyapi.com/api/character/%3Fpage=3
The class that gets information from the API
class Api {
final String _baseUrl = 'rickandmortyapi.com';
final String _charactersUrl = '/api/character/?page=2';
final String _charactersJsonKey = 'results';
final HttpClient _httpClient = HttpClient();
Future<List<Character>> getCharacters() async {
final uri = Uri.https(_baseUrl, _charactersUrl);
final response = await _getJson(uri);
if (response == null || response[_charactersJsonKey] == null) {
print('Api.getCharacters(): Error while retrieving characters');
return null;
}
return _convert(response[_charactersJsonKey]);
}
Future<Map<String, dynamic>> _getJson(Uri uri) async {
try {
final request = await _httpClient.getUrl(uri);
final response = await request.close();
if (response.statusCode != HttpStatus.OK) {
print('Api._getJson($uri) status code is ${response.statusCode}');
return null;
}
final responseBody = await response.transform(utf8.decoder).join();
return json.decode(responseBody);
} on Exception catch (e) {
print('Api._getJson($uri) exception thrown: $e');
return null;
}
}
List<Character> _convert(List charactersJson) {
List<Character> characters = <Character>[];
charactersJson.forEach((character) {
characters.add(Character.fromJson(character));
});
return characters;
}
}
I would be very grateful if someone could help me. Thanks!
The Uri class expects you to use the Uri.https constructor differently.
The third positional parameter is queryParameters, which you should use instead of passing your query parameters to the unencodedPath:
final String _baseUrl = 'rickandmortyapi.com';
final String _charactersPath = '/api/character/';
final Map<String, String> _queryParameters = <String, String>{
'page': '2',
};
Future<List<Character>> getCharacters() async {
final uri = Uri.https(_baseUrl, _charactersPath, _queryParameters);
...