I want to upload images to the server using flutter and HTTP package. I am able to display user-selected images but I want to upload them to the server but when I try to pass the image file to the function it gives me an error.
Image Picker Code :
XFile? uploadimage;
final ImagePicker _picker = ImagePicker();
Future<void> chooseImage() async {
var chooseImage = await _picker.pickImage(source: ImageSource.gallery);
setState(() {
uploadimage = chooseImage;
});
}
**services file code **
AdminSupervisorServices.createNewSupervisor(
_nameController.text,
_emailController.text,
_addressController.text,
_siteController.text,
_mobileController.text,
_passwordController.text,
uploadimage // error here
)
function body
static createNewSupervisor(String name, String email, String address,
String site, String mobileNumber, String password, File? image) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
List<int> imageBytes = image!.readAsBytesSync();
String baseimage = base64Encode(imageBytes);
var token = prefs.getString("token");
var response = await http
.post(Uri.parse("$baseURL/api/mmmmmmmm"), headers: {
'Authorization': 'Bearer $token',
}, body: {
"full_name": name,
"address": address,
"mobile_no": mobileNumber,
"email": email,
"site_name": site,
"password": password,
"image": baseimage,
});
print(response.body.toString());
var data = jsonDecode(response.body);
return data;
}
...
}
try this
if this work
import 'dart:io';
/////// Import for File
final File uploadimage = File("");
final ImagePicker _picker = ImagePicker();
Future<void> chooseImage() async {
var chooseImage = await _picker.pickImage(source: ImageSource.gallery);
setState(() {
uploadimage = File(chooseImage.path);
});
}
the function you have
AdminSupervisorServices.createNewSupervisor(
_nameController.text,
_emailController.text,
_addressController.text,
_siteController.text,
_mobileController.text,
_passwordController.text,
uploadimage
);
static createNewSupervisor(String name, String email, String address,
String site, String mobileNumber, String password, File? image)async{
...
}
Edit:
if you are passing image to a json
then you missing out is data:image/png;base64 something like this
lets assume this function return string.
///include import path
import 'package:path/path.dart' as path;
///////////////////////////////////////
imagetobase64(String? imagePath){
final extension = path.extension(imagePath
.substring(imagePath.lastIndexOf("/"))
.replaceAll("/", ""));
//// the extension return is png or jpg or jpeg which is needed
final bytes = File(imagePath).readAsBytesSync();
String base64 =
"data:image/${extension.replaceAll(".", "")};base64,${base64Encode(bytes)}";
return base64;
}
uploadimage is of type XFile? and you are passing it to a function which accepts parameter of File? type
Related
can anyone please help me?, I created a login function with api, when the user wants to login and succeeds then it is directed to the profilescreen the user details appear, but when it switches to the homescreen and switches to the profilescreen again, the user details that previously appeared are lost and become null.
I thought of using sharedpreferences to save user response data after login, but I don't know if it was saved or not
Future<LoginModels> postLogin(String email, String password) async {
var dio = Dio();
String baseurl = url;
Map<String, dynamic> data = {'email': email, 'password': password};
try {
final response = await dio.post(
'$baseurl/api/login',
data: data,
options: Options(headers: {'Content-type': 'application/json'}),
);
print('Respon -> ${response.data} + ${response.statusCode}');
if (response.statusCode == 200) {
final loginModel = LoginModels.fromJson(response.data);
return loginModel;
}
} catch (e) {
print('Error di $e');
}
return LoginModels();}
i tried adding sharedpreference in the part after response.statuscode == 200 , like this
SharedPreferences pref = await SharedPreferences.getInstance();
String jsonUser = jsonEncode(loginModel);
pref.setString('userDetail', jsonUser);
print('data nih $jsonUser');
and the output is like this
LoginModels loginModelsFromJson(String str) => LoginModels.fromJson(
json.decode(str),
);
String loginModelsToJson(LoginModels data) => json.encode(data.toJson());
class LoginModels {
LoginModels({
this.isActive,
this.message,
this.data,
});
bool? isActive;
String? message;
Data? data;
factory LoginModels.fromJson(Map<String, dynamic> json) => LoginModels(
isActive: json["is_active"],
message: json["message"],
data: Data.fromJson(json["data"]),
);
Map<String, dynamic> toJson() => {
"is_active": isActive,
"message": message,
"data": data?.toJson(),
};
}
class Data {
Data({
this.iduser,
this.nama,
this.profesi,
this.email,
this.password,
this.roleId,
this.isActive,
this.tanggalInput,
this.modified,
});
String? iduser;
String? nama;
String? profesi;
String? email;
String? password;
String? roleId;
String? isActive;
String? tanggalInput;
String? modified;
factory Data.fromJson(Map<String, dynamic> json) => Data(
iduser: json["iduser"],
nama: json["nama"],
profesi: json["profesi"],
email: json["email"],
password: json["password"],
roleId: json["role_id"],
isActive: json["is_active"],
tanggalInput: json["tanggal_input"],
modified: json["modified"],
);
Map<String, dynamic> toJson() => {
"iduser": iduser,
"nama": nama,
"profesi": profesi,
"email": email,
"password": password,
"role_id": roleId,
"is_active": isActive,
"tanggal_input": tanggalInput,
"modified": modified,
};
}
class User {
String? id;
String? nama;
String? profesi;
String? email;
String? password;
String? roleId;
String? isActive;
String? tanggalInput;
String? modified;
User();
User.fromJson(Map<String, dynamic> json)
: id = json["iduser"],
nama = json['nama'],
profesi = json['profesi'],
email = json['email'],
password = json['password'],
roleId = json['role_id'],
isActive = json['is_active'],
tanggalInput = json['tanggal_input'],
modified = json['modified'];
Map<String, dynamic> toJson() => {
'id': id,
'nama': nama,
'profesi': profesi,
'email': email,
'password': password,
'role_id': roleId,
'is_active': isActive,
'tanggal_input': tanggalInput,
'modified': modified,
};
}
if it is already stored how do I retrieve the data? or is there another alternative to solve the problem I have?
you can use key-value for store in pref. if u want to save user's email,name,id than store it like this (note:this is example of GetX)
//to store data
var storeUserData = Get.find<SharedPreferences>();
storeUserData.setString('use_name',userName);
// to retrive data
var userName = storeUserData.getString('use_name');
set this userName to your profilescreen's text and you are done.
While storing this in SharedPreferences call the toMap() method on the object This will return a Map<String, dynamic> representation of your current object.
Map<String, dynamic> productsMap = products.toMap();
After that Convert the object to String by using json.encode() and store it !
storedCart(productsMap){
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString('userData', json.encode(productsMap));
}
you'll notice that when we convert our object to JSON it becomes a big String, Therefore it is possible for us to store it in SharedPreferences using the "putString()" method.
Also you can store single single value store in SharedPreferences
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString("user", token);
Also When you want to get data from sharedPref
you have to call
var value = prefs.getString(key);
After that you have to decode the value.
var decodeValue = json.decode(value)
final loginModel = LoginModels.fromJson(decodeValue).
after that you can find every data base on your model class
Don't forget to use .apply() once you update the fields in the code.
I'm working on a project that fetches pdf file from the internet then have to encrypt and store it on the device. Then for future use, it has to decrypt the encrypted pdf file and load it.
This is the method to fetch the pdf file :
Future<String> fetchThenStorePdf(DownloadedBook book) async {
var pdfPath = await getBookUrl(book);
book.bookFilePath = Uri.http('http://www.marakigebeya.com.et/mabdocuments/audio_e_books/fa872915-f364-4129-b373-06c1df078c00..pdf', pdfPath).toString();
final response = await client
.get(Uri.parse('${book.bookFilePath}'))
.timeout(Duration(minutes: 3), onTimeout: () {
throw Exception('connection timed out');
});
if (response.statusCode == 200) {
print('The pdf file is ${response.bodyBytes}');
return await storeEncryptedPdf(
response.body,
bookTitle: book.title,
);
} else {
throw Exception('PDF file not found');
}
}
This method will call storeEncryptedPdf() method which looks like :
Future<String> storeEncryptedPdf(String pdfByteFile,
{required String bookTitle}) async {
await PermissionHandler.requestStoragePermission();
try {
var directory = await getApplicationDocumentsDirectory();
var bookDirectory = await Directory(path.join(
'${directory.path}',
'books',
)).create(recursive: true);
final filePath = path.join(bookDirectory.path, '$bookTitle');
final file = File(filePath);
var encryptedData = encryptionHandler.encryptData(pdfByteFile);
await file.writeAsString(encryptedData, flush: true);
return filePath;
} catch (e) {
throw Exception('File encryption failed');
}
}
which inturn will call the encryptData() method:
String encryptData(String fileToEncrypt) {
key = Key.fromUtf8(encryptionKeyString);
iv = IV.fromUtf8(encryptionKeyString);
final encrypter = Encrypter(
AES(
key,
padding: null,
),
);
Encrypted encrypted = encrypter.encrypt(
fileToEncrypt,
iv: iv,
);
return encrypted.base64;
}
I used the encrypt: ^5.0.1 flutter package for the encryption and deccription.
The decryption method is :
Future<String> decryptStoredPdf(String filePath) async {
encryptionHandler.encryptionKeyString = 'theencryptionkey';
final file = File(filePath);
final byteFile = await file.readAsString();
return encryptionHandler.decryptData(byteFile);
}
where filepath is the path of the file stored. This method finally calls the method decryptData :
String decryptData(String filetoDecrypt) {
key = Key.fromUtf8(encryptionKeyString);
iv = IV.fromUtf8(encryptionKeyString);
final encrypter = Encrypter(
AES(
key,
padding: null,
),
);
String decrypted = encrypter.decrypt(
Encrypted.from64(filetoDecrypt),
iv: iv,
);
return decrypted;
}
But all this is not working.
Can someone pls replicate this and try to figure out what the problem is
You have to manipulate with bytes, but not with strings. Just read bytes, encrypt/decrypt bytes, create/read file from bytes.
I would like to make a get requests and to convert results to a list of objects.
Actually i did that :
post_model.dart
#JsonSerializable()
class Post {
Post({
required this.userId,
required this.id,
required this.title,
required this.body,
});
factory Post.fromJson(Map<String, dynamic> json) => _$PostFromJson(json);
Map<String, dynamic> toJson() => _$PostToJson(this);
final int userId;
final int id;
final String title;
final String body;
}
http_service.dart :
class HttpService {
final String url = 'https://jsonplaceholder.typicode.com';
final String postsURL = '/posts';
final Map<String, String> headers = {
'Content-Type': 'application/json'
};
List<Post> parsePosts(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Post>((json) => Post.fromJson(json)).toList();
}
Future<List<Post>> fetchPosts() async {
final http.Response response = await http.get(Uri.https(url, postsURL));
if (response.statusCode == 200) {
return compute(parsePosts,response.body);
} else {
throw Exception("Failed to load posts ${response.statusCode}");
}
}
}
But i encouter all in red on the parsePosts method.
On the final parsed :
Missing variable type for 'parsed'.
Try adding an explicit type, or remove implicit-dynamic from your analysis options file.dart(implicit_dynamic_variable)
and on the return :
A value of type 'dynamic' can't be returned from the method 'parsePosts' because it has a return type of 'List<Post>'
I just don't understand what i'm doing wrong, because i have follow the flutter doc here :
https://flutter.dev/docs/cookbook/networking/background-parsing
Thanks for any help
Some time ago I did this code for that API:
import 'dart:async';
import 'package:wnetworking/wnetworking.dart';
class Post {
int? userId, id;
String? title, body;
Post.fromJson(Map<String, dynamic> data) {
userId = data['userId'];
id = data['id'];
title = data['title'];
body = data['body'];
}
}
class JsonPlaceHolder {
static const baseUrl = 'https://jsonplaceholder.typicode.com';
/* ---------------------------------------------------------------------------- */
static FutureOr<void> _doGet(String path, {void doThis(var response)?}) async {
await HttpReqService.getJson(baseUrl + path)
.then((response) => doThis == null ? print(response) : doThis(response))
.whenComplete(() => print('\nFetching done!'));
}
/* ---------------------------------------------------------------------------- */
static FutureOr<void> _doPost(String path, {required Object body, int okCode = 200}) async {
await HttpReqService.post<Map<String, dynamic>>(baseUrl + path, body: body, okCode: okCode)
.then((response) => print(response))
.whenComplete(() => print('\nPost sent successfully'));
}
/* ---------------------------------------------------------------------------- */
static FutureOr<void> fetchPosts({int? id, bool onlyComments = false, bool useObjList = false}) async {
var path = '/posts/${id ?? ''}';
if (id != null && onlyComments) path += '/comments';
useObjList
? await _doGet(path, doThis: (response) {
if (response != null) {
print((response as List).map<Post>((m) => Post.fromJson(m as Map<String, dynamic>)));
}
})
: await _doGet(path);
}
/* ---------------------------------------------------------------------------- */
static FutureOr<void> fetchComments([int? postId]) => _doGet('/comments${postId != null ? '?postId='+postId.toString() : ''}');
static FutureOr<void> fetchAlbums() => _doGet('/albums');
static FutureOr<void> fetchPhotos() => _doGet('/photos');
static FutureOr<void> fetchTodos() => _doGet('/todos');
static FutureOr<void> fetchUsers() => _doGet('/users');
}
void main(List<String> args) async {
// await JsonPlaceHolder.fetchComments(1);
await JsonPlaceHolder.fetchPosts(useObjList: true);
print('Finished!');
}
Result:
(Instance of 'Post', Instance of 'Post', Instance of 'Post', ..., Instance of 'Post', Instance of 'Post')
Fetching done!
Finished!
Note
wnetworking package is not ready to publish yet, it contains operations related to API, etc. You can replace HttpReqService.getJson and HttpReqService.post with your typical http.get and http.post respectively but keep in mind the return value and exceptions.
Use Uri.parse
Those errors are due to a dart version.
A fix has been made by another user on github : https://github.com/flutter/website/pull/5798
Following this PR, it's works
im trying to make this app to learn the methods to use in Firebase, now, im using Cloud Firestore + Storage, but im getting this error:
Exception has occurred.
FirebaseException ([firebase_storage/object-not-found] No object exists at the desired reference.)
im soo new on firebase so i dont know what to do... also there were a lot of updates and changes and some replies in other posts are deprecated ...
Future<void> uploadPic(File foto) async {
final Reference postImageRef = FirebaseStorage.instance.ref().child('Post Images');
var timeKey = DateTime.now();
await postImageRef.child(timeKey.toString() + "jpg").putFile(foto)
.whenComplete(() async { //IM GETTING THE ERROR HERE
await postImageRef.getDownloadURL().then((value) { //IM GETTING THE ERROR HERE
posts.imageUrl = value;
});
});
return posts.imageUrl;
}
and here is the submit of the button "save"
void _submit() async {
if (!formKey.currentState.validate()) return null;
formKey.currentState.save();
uploadPic(foto);
subirPost(posts);
print(posts.datetime);
mostrarToast('Producto guardado');
}
The error here is that you do not wait for the downloaded image link to return to you using this method:
Note: If you want to upload and write at the same time, you must wait for the completion of the lifting and then write.
1- First, create an external file that contains all the related services in Firebase, let's say its name is Api, and add this method in it:
static Future<dynamic> postFile(
{#required File imageFile, #required String folderPath}) async {
String fileName = DateTime.now().millisecondsSinceEpoch.toString();
Reference reference =
FirebaseStorage.instance.ref().child(folderPath).child(fileName);
TaskSnapshot storageTaskSnapshot =await reference.putFile(imageFile);
print(storageTaskSnapshot.ref.getDownloadURL());
var dowUrl = await storageTaskSnapshot.ref.getDownloadURL();
return dowUrl;
}
2- When the image is uploaded, this method will return you the link to download the image in Firebase, store it in the object as described below:
String imgUrl = await Api.postFile(
imageFile: image,
folderPath: 'image');
if (imgUrl != null) {
posts.imageUrl = imgUrl;
///Type here the command that will write to the firestore
}
Check Out This Working Code
Need An uuid Package: https://pub.dev/packages?q=uuid
File _image;
final pickedFile = await ImagePicker()
.getImage(source: ImageSource.camera, imageQuality: 80);
final String filePath = pickedFile != null ? pickedFile.path : '';
if (filePath.isNotEmpty) {
_image = File(filePath);
if (_image != null) {
if (_image != null) {
final Reference sref = storageReference
.child('chat_multimedia/images/')
.child(uuid.v4());
final UploadTask storageUploadTask = sref.putFile(
_image,
SettableMetadata(
contentType: mime(basename(_image.path)),
),
);
if (storageUploadTask.snapshot.state == TaskState.success) {
final String url = await sref.getDownloadURL();
print('The download URL is ' + url);
} else if (storageUploadTask.snapshot.state == TaskState.running) {
storageUploadTask.snapshotEvents.listen((event) {
percentage = 100 *
(event.bytesTransferred.toDouble() /
event.totalBytes.toDouble());
print('THe percentage ' + percentage.toString());
});
} else {
print('Enter A valid Image');
}
await storageUploadTask.whenComplete(() async {
final String downloadUrl = await sref.getDownloadURL();
});
}
}
}
I'm trying to send a Base64 string to a server using Requests package. I'm getting the image file using Flutter image Picker package, here is a snip of my code:
Getting the Image
File _image;
final picker = ImagePicker();
final picker = ImagePicker();
Future getImage() async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
_image = File(pickedFile.path);
});
}
Converting and sending it
List<int> imageBytes = _image.readAsBytesSync();
String base64Image = base64Encode(imageBytes);
var r = await Requests.post(
'my_URL',
headers: {'content-type': 'multipart/form-data'},
body: {
'image':'$base64Image',
}
);
This send null to the server, any suggestion about how to do it in the right way?
Change this line
List<int> imageBytes = _image.readAsBytesSync();
To
List<int> imageBytes = await _image.readAsBytesSync();
It could help.