How to Show Snackbar with the Result of Future Http Post? - flutter

I'm trying to get a "File was uploaded." string back from a successful Future HTTP post request so that I can create a SnackBar but all I get back from the return is null. Here's the button which calls the Future;
IconButton(
icon: Icon(TriangleAll.upload_3, ),
onPressed: () async {
replyresult = await uploadReply(
filepath: _current.path);
)
if (replyresult != null){
print(replyresult);
}
}
)
And here's the code for the future;
Future<String> uploadReply(
}) async {
final serverurl = "http://example.com/example.php";
final filepath = "examplefilepath";
String serverResponse;
var request = http.MultipartRequest('POST', Uri.parse(serverurl));
var multiPartFile = await http.MultipartFile.fromPath("audio", filepath,
contentType: MediaType("audio", "mp4"));
request.files.add(multiPartFile);
request.send().then((result) async {
http.Response.fromStream(result).then((response) {
if (response.statusCode == 200) {
serverResponse = response.body;
print(serverResponse);
return serverResponse ;
}
});
});
}
I'm trying to use the replyresult variable to create the snackbar upon a successful 200 server response. I know the post is successful as I can see the correct printed serverResponsein the console.
I've tried to simply do;
return response.body ;
But I'm still getting null at the replyresult variable.

because the method returns before the response arrives in Future, do this
var response = await http.Response.fromStream(result);
if (response.statusCode == 200) {
serverResponse = response.body;
print(serverResponse);
return serverResponse ;
} else return '';
or a single await ahead of the Future.

This is what worked.
var multiPartFile = await http.MultipartFile.fromPath("audio", filepath,
contentType: MediaType("audio", "mp4"));
request.files.add(multiPartFile);
final response = await http.Response.fromStream(await request.send());
String serverResponse;
if (response.statusCode == 200) {
String serverResponse = response.body;
print(serverResponse);
return serverResponse;
}

Related

Flutter: How to send multiple images using for loop

I am using http package to perform multipart request.I am trying to upload multiple images using for loop but I am not getting any idea how to do it following is my postman response in the below image you can see 2 fields one is attribute and another one is image here I want to loop only adhar and pan inside attributes after sending "mobileno":"4567654","role":"p","userstatus":"D", to database
following is my multipart request code
Future<void> insertCategory(String category, BuildContext context) async {
var flutterFunctions =
Provider.of<FlutterFunctions>(context, listen: false);
var data = {"mobileno":"4567654","role":"p","userstatus":"D","adhar":"adhar","pan":"pan"};
var url = PurohitApi().baseUrl + PurohitApi().insertcategory;
Map<String, String> obj = {"attributes": json.encode(data).toString()};
try {
loading();
final client = RetryClient(
http.Client(),
retries: 4,
when: (reponse) {
return reponse.statusCode == 401 ? true : false;
},
onRetry: (request, response, retryCount) async {
if (retryCount == 0 && response?.statusCode == 401) {
var accesstoken = await Provider.of<Auth>(context, listen: false)
.restoreAccessToken();
request.headers['Authorization'] = accesstoken;
print(accesstoken);
}
},
);
var response = await http.MultipartRequest('Post', Uri.parse(url))
..files.add(await http.MultipartFile.fromPath(
"imagefile", flutterFunctions.imageFile!.path,
contentType: MediaType("image", "jpg")))
..headers['Authorization'] = token!
..fields.addAll(obj);
final send = await client.send(response);
final res = await http.Response.fromStream(send);
var messages = json.decode(res.body);
loading();
print(messages);
} catch (e) {
print(e);
}
}
Future<Object> addUserImages(List<XFile> files, String userID, String token) async {
try {
var url = Uri.parse(API_BASE_URL + addUserImagesUrl);
var request = http.MultipartRequest("POST", url);
request.headers['Authorization'] = "Bearer ${StaticServices.userBaseModel!.token!.token}";
for (var i = 0; i < files.length; i++) {
String fileName = DateTime.now().microsecondsSinceEpoch.toString().characters.takeLast(7).toString();
var pic = http.MultipartFile.fromBytes("files", await File(files[i].path).readAsBytes(), filename: '${userID}_${i}_$fileName', contentType: MediaType("image", files[i].mimeType ?? "png"));
//add multipart to request
request.files.add(pic);
}
var response = await request.send();
var responseData = await response.stream.toBytes();
var responseString = String.fromCharCodes(responseData);
if (response.statusCode == 200) {
return Success(response: Images.fromJson(jsonDecode(responseString)));
}
return Failure(
errorMessage: responseString,
);
} on HttpException {
return Failure(errorMessage: "No Internet Connection");
} on FormatException {
return Failure(errorMessage: "Invalid Format");
} on SocketException {
return Failure(errorMessage: "No Internet Connection");
} catch (e) {
return Failure(errorMessage: "Invalid Error");
}
}

How to refresh token and retry request on 401 error using Flutter

I try to refresh token and retry request on 401 error, but can not understand how to do it by right way
This is a recreation from what I remember so there can be typo and small errors maybe.
I hope you get an idea what I am trying to do here.
import 'package:http/http.dart' as http;
class APIUtility {
Uri uri;
String path, method;
var body;
var headers;
APIUtility({ #required this.path, #required this.method, this.body}) {
this.uri = Uri.parse("http://localhost:4000/api/${this.path}");
this.headers = {'Content-Type': 'application/json'};
}
Future request({ bool useToken = true }) async {
http.Response response;
if ( useToken ) { this.header['token'] = await getAccessToken(); }
try {
response = await // call api with http package with correct path, method and body
if ( useToken && response.statusCode == 401 ) return await _refreshTokenAndRequest();
else return jsonDecode(response.data);
}
catch (e) {
print(e);
return null;
}
}
_refreshTokenAndRequest() async {
String accessToken = await getAccessToken();
String refreshToken = await getRefreshToken();
var body = {'access_token': accessToken, 'refresh_token': refreshToken};
http.Response response = await http.post("${this.baseUrl}/api/auth/refresh", body: body);
if (response.statusCode == 200 || response.statusCode == 201) {
saveAccessToken(response.body['access_token']);
saveRefreshToken(response.body['refresh_token']);
return await request();
} else {
// Logout user from app
// Delete all database, token and all user info and show login screen;
return null;
}
}
}

Image Upload in Flutter Using Http post method

I'm new in this Framework and I want to Upload the Image along with the User name id and wmail and phone,
but Unable to to that I'm getting error
this is the Image get image function
File _image;
final picker = ImagePicker();
Future getImage() async {
pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
if (pickedFile != null) {
_image = File(pickedFile.path);
} else {
print('No image selected.');
}
});
}
Here i have written the Code for Upkoadung How to do Please help me with that
Future updateUserApiCall(
String name, String email, String mobile, File profile) async {
String token;
var userId;
SharedPreferences storage = await SharedPreferences.getInstance();
token = storage.getString("apiToken");
userId = storage.getInt("id");
String url = "https://www.example.com/api/updateprofile";
final response = await http.post(
url + "?page=" + "",
body: json.encode({
'user_id': userId,
'email': email,
'name': name,
'phone': mobile,
'image': profile,
}),
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": "Bearer " + token,
},
);
if (response.statusCode == 200) {
print(response.body);
return UpdateProfileResponseModel.fromJson(
json.decode(response.body),
);
} else if (response.statusCode == 400) {
print(response.body);
return ErrorResponseModel.fromJson(
json.decode(response.body),
);
} else if (response.statusCode == 422) {
print(response.body);
return ValidationErrorResponseModel.fromJson(
json.decode(response.body),
);
} else {
print(response);
throw Exception('Failed to load data!');
}
}
}
As far as I know you can not pass image data using just http.post method. You have to use Multipart Request. I have also faced similar problem and asked a similar question in StackOverFlow. Please check the link below:
uploading image using file_picker flutter to a nodejs server
My use case was updating image of an user, I have used the following code to send image to a node server.
Future<bool> updateImage(File imageFile, AuthModel authModel) async{
final String _accessToken = 'abc';
final String url =
'https://justyourserverURL.com/update';
print("auth : " + _accessToken);
var request = http.MultipartRequest('POST', Uri.parse(url));
request.headers['Authorization'] = _accessToken;
// request.fields['id'] = '104';
// request.fields['firstName'] = authModel.data.firstName;
// request.fields['lastName'] = authModel.data.lastName;
// request.fields['surname'] = authModel.data.surname;
request.files.add(await http.MultipartFile.fromPath('file', imageFile.path));
var res = await request.send();
final respStr = await res.stream.bytesToString();
print('responseBody: ' + respStr);
if(res.statusCode==200){
setCurrentUser(respStr);
currentUser = authModelFromJson(respStr);
return true;
} else {
print(respStr);
print('Failed');
return false;
}
}
To pass username or id just pass data using request.fields['user_id'] = userId.

Flutter - Before .then is executed, Function is returning the value and after that reading .then

I am facing 2 problems with the below code and I think both are related.
createFunction is showing an error -
"This function has a return type of 'FutureOr< bool >', but doesn't end with a return statement. Try adding a return statement, or changing the return type to 'void'." - I need to return true or false, so I have to use return type bool.
When the function is executed, it runs smoothly till the PROBLEM AREA (marked in the code). Here it returns null and then comes back to execute .then . I need to run .then right after http.post is executed. At the end of the code it should return true / false.
Any help will be highly appreciated.
Future<bool> createFunction(image) async {
var request = new http.MultipartRequest("POST", Uri.parse(_urlImage));
request.files.add(
await http.MultipartFile.fromPath('imagefile', image));
var response = await request.send().catchError((error) {
throw error;
});
response.stream.transform(utf8.decoder).listen((value) async {
return await http
.post(
_url,
headers: {
'content-type': 'application/json',
'authorization': 'auth'
},
body: json.encode({data}),
)
///// PROBLEM AREA //////
.then((value) async {
final _extractedData = await jsonDecode(value.body);
if (value.statusCode == 201) {
return true;
} else {
return false;
}
}).catchError((error) {
throw error;
});
});
}
Ok, for the next visitors to this page, the correct usage of MultipartRequest class should like this:
var uri = Uri.parse('https://example.com/create');
var request = http.MultipartRequest('POST', uri)
..fields['user'] = 'nweiz#google.com'
..files.add(await http.MultipartFile.fromPath(
'package', 'build/package.tar.gz',
contentType: MediaType('application', 'x-tar')));
var response = await request.send();
if (response.statusCode == 200) print('Uploaded!');

how to upload image to rest API in flutter through http post method?

I'm trying to upload an image through the flutter via post method. and I'm using image_picker for pick file from mobile but I can't able to upload
and I have tried to send the file like FormData that also doesn't work
Future<dynamic> uploadLicence(int id ,dynamic obj) async {
FormData formdata = new FormData(); // just like JS
formdata.add("image",obj);
final response = await post('Logistic/driver/LicenceImage?
driverId=$id',
formdata);
print(response);
// return null;
if (response.statusCode == 200) {
final result = json.decode(response.body);
return result;
} else {
return null;
}
}
after that, I just tried with this method but this also not working
Future<dynamic> uploadLicence(int id, File file) async {
final url = Uri.parse('$BASE_URL/Logistic/driver/LicenceImage?
driverId=$id');
final fileName = path.basename(file.path);
final bytes = await compute(compress, file.readAsBytesSync());
var request = http.MultipartRequest('POST', url)
..files.add(new http.MultipartFile.fromBytes(
'image',bytes,filename: fileName,);
var response = await request.send();
var decoded = await
response.stream.bytesToString().then(json.decode);
if (response.statusCode == HttpStatus.OK) {
print("image uploded $decoded");
} else {
print("image uplod failed ");
}
}
List<int> compress(List<int> bytes) {
var image = img.decodeImage(bytes);
var resize = img.copyResize(image);
return img.encodePng(resize, level: 1);
}
It's possible with MultipartRequest. Or you can use simply dio package. It's one command.
With http:
import 'package:http/http.dart' as http;
final Uri uri = Uri.parse(url);
final http.MultipartRequest request = http.MultipartRequest("POST", uri);
// Additional key-values here
request.fields['sample'] = variable;
// Adding the file, field is the key for file and file is the value
request.files.add(http.MultipartFile.fromBytes(
field, await file.readAsBytes(), filename: filename);
// progress track of uploading process
final http.StreamedResponse response = await request.send();
print('statusCode => ${response.statusCode}');
// checking response data
Map<String, dynamic> data;
await for (String s in response.stream.transform(utf8.decoder)) {
data = jsonDecode(s);
print('data: $data');
}
I user this code for my project i hope work for you
Upload(File imageFile) async {
var stream = new http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
var length = await imageFile.length();
var uri = Uri.parse(uploadURL);
var request = new http.MultipartRequest("POST", uri);
var multipartFile = new http.MultipartFile('file', stream, length,
filename: basename(imageFile.path));
//contentType: new MediaType('image', 'png'));
request.files.add(multipartFile);
var response = await request.send();
print(response.statusCode);
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}