this is how I upload images to firebase storage and get the Download URL in firebase Firestore. Everything works properly how ever I get the 1st URL but not the Second one.
Future<void> uploadImage2(image2) async {
setState(() {
isLoader2 = true;
});
final bytess = image2.readAsBytesSync();
var timeStamp = DateTime.now();
final metadata = firebase_storage.SettableMetadata(contentType: 'CarImage');
firebase_storage.UploadTask task = firebase_storage.FirebaseStorage.instance
.ref('Toyota-Images/$timeStamp/2.png')
.putData(bytess, metadata);
firebase_storage.TaskSnapshot downloadUrl2 = (await task);
String url = (await downloadUrl2.ref
.getDownloadURL()); //this is the url of uploaded image
imageUrl2 = url;
setState(() {
isLoader2 = false;
});
}
Future<void> uploadImage3(image3) async {
setState(() {
isLoader3 = true;
});
final bytess = image3.readAsBytesSync();
var timeStamp = DateTime.now();
final metadata = firebase_storage.SettableMetadata(contentType: 'CarImage');
firebase_storage.UploadTask task = firebase_storage.FirebaseStorage.instance
.ref('Toyota-Images/$timeStamp.png')
.putData(bytess, metadata);
firebase_storage.TaskSnapshot downloadUrl3 = (await task);
String url = (await downloadUrl3.ref
.getDownloadURL()); //this is the url of uploaded image
imageUrl3 = url;
setState(() {
isLoader3 = false;
});
}
You can upload image to firebase as below
First of all you need to add this plugin in pubspec.yaml
firebase_storage: ^8.0.0
import 'package:firebase_storage/firebase_storage.dart' as firebase_storage;
Future<void> uploadFile(File _image) async {
setState(() {
isLoader = true;
});
final bytess = _image.readAsBytesSync(); //"_image" is your selected image or any other which you need to upload
var timeStamp = DateTime.now();
final metadata = firebase_storage.SettableMetadata(contentType: 'image/jpeg');
firebase_storage.UploadTask task = firebase_storage.FirebaseStorage.instance
.ref('cover_photo/'+timeStamp.toString()+'insp_cover_photo.png').putData(bytess,metadata);
firebase_storage.TaskSnapshot downloadUrl = (await task);
String url = (await downloadUrl.ref.getDownloadURL()); //this is the url of uploaded image
setState(() {
isLoader = false;
});
}
Let me know if you have any questions
You can do it using firebase_storage.
you can get url by using this function.
Future<String> uploadFile(File _imageFile) async {
String fileName = DateTime.now().millisecondsSinceEpoch.toString();
Reference reference = FirebaseStorage.instance.ref().child(fileName);
UploadTask uploadTask = reference.putFile(_imageFile);
return uploadTask.then((TaskSnapshot storageTaskSnapshot) {
return storageTaskSnapshot.ref.getDownloadURL();
}, onError: (e) {
throw Exception(e.toString());
});
}
Related
I define pick image and photoUrl variables:
File? image;
String? photoUrl;
This is my pick image method:
Future pickImage(ImageSource source) async {
try {
final image = await ImagePicker().pickImage(source: ImageSource.gallery);
if (image == null) return;
final imageTemporary = File(image.path);
setState(() {
this.image = imageTemporary;
});
} on PlatformException catch (e) {
print('Failed to pick image : $e');
}
}
This is my upload image function ı upload image with current user ids:
Future uploadFile() async {
final path = '${_auth.currentUser!.uid}.jpg';
final file = File(image!.path);
final ref = FirebaseStorage.instance
.ref()
.child('images/${_auth.currentUser!.uid}.jpg');
task = await ref.putFile(file);
//final url = await ref.getDownloadURL();
//print('Download URLLLLLLLLLLLLLLLLLLLLL : $url');
/*
I saved download image url to setstate method
setState(() {
photoUrl = url.toString();
});
*/
}
This is my download image and init state method, when I upload image to firebase storage first time, ı am getting no object exist at desired reference error, but after ı upload image then I try
to download image and I want to show in image.network it works, How can I fix this error when I try to upload and download first time without error ?
Future downloadImage() async {
final ref = FirebaseStorage.instance
.ref()
.child('images/${_auth.currentUser!.uid}.jpg');
final url = await ref.getDownloadURL();
print('Download URLLLLLLLLLLLLLLLLLLLLL : $url');
setState(() {
photoUrl = url.toString();
});
}
#override
initState() {
// TODO: implement initState
super.initState();
downloadImage();
}
This is my error:
and
this is my storage its empty :
The problem seems to be that you are trying to get the url before uploading the image, Here is what you can do :
uploadImage() async {
final _firebaseStorage = FirebaseStorage.instance;
final _imagePicker = ImagePicker();
PickedFile image;
//Check Permissions
await Permission.photos.request();
var permissionStatus = await Permission.photos.status;
if (permissionStatus.isGranted){
//Select Image
image = await _imagePicker.getImage(source: ImageSource.gallery);
var file = File(image.path);
if (image != null){
//Upload to Firebase
var snapshot = await _firebaseStorage.ref()
.child('images/imageName')
.putFile(file).onComplete;
var downloadUrl = await snapshot.ref.getDownloadURL();
setState(() {
imageUrl = downloadUrl;
// in here you can add your code to store the url in firebase database for example:
FirebaseDatabase.instance
.ref('users/$userId/imageUrl')
.set(imageUrl)
.then((_) {
// Data saved successfully!
})
.catchError((error) {
// The write failed...
});
});
} else {
print('No Image Path Received');
}
} else {
print('Permission not granted. Try Again with permission access');
}
source How to upload to Firebase Storage with Flutter
I hope this will be helpfull
so this is the my file picking and file upload code
class Storage with ChangeNotifier {
PlatformFile? pickedFile;
UploadTask? uploadTask;
Future uploadFile() async {
final path = 'files/${pickedFile!.name}.png';
final file = File(pickedFile!.path!);
final ref = FirebaseStorage.instance.ref().child(path);
ref.putFile(file);
try {
final snapshot = await uploadTask!.whenComplete(() {});
final urlDownload = await snapshot.ref.getDownloadURL();
print(urlDownload);
} catch (e) {
print("this is the error $e " );
}
}
void pickFile() async {
FilePickerResult? result = await FilePicker.platform.pickFiles();
if (result != null) {
File file = File(result.files.single.path!);
pickedFile = result.files.first;
} else {
print("no image picked");
}}}
the code works for upload the image but after that i didnt get any download link, the error is "Null check operator used on a null value" i dont know how to fix it, im still new in this topic, help please
i got the answer, need to change the uploadFile method to this
Future uploadFile() async {
final path = 'files/${pickedFile!.name}.png';
final file = File(pickedFile!.path!);
FirebaseStorage storage = FirebaseStorage.instance;
Reference ref = storage.ref().child(path);
UploadTask uploadTask = ref.putFile(file);
uploadTask.then((res) {
res.ref.getDownloadURL();
});
try {
final snapshot = await uploadTask.whenComplete(() {});
final urlDownload = await snapshot.ref.getDownloadURL();
print(urlDownload);
} catch (e) {
print("this is the error $e " );
}
}
I am trying to upload multiple (max 5) xfiles images (image_picker library) to firebase storage. currently, it uploads only one with the below method:
Future<void> addProduct({
BuildContext? ctx,
String? proName,
String? productDescription,
double? count,
double? price,
required List<XFile> images
}) async {
try {
var imageUrls = await Future.wait(images.map((_image) =>
uploadFile(_image)));
await firestore
.collection(outletsCollection)
.doc(_currentUserOutletId)
.set({
products: FieldValue.arrayUnion([
{
productId: Uuid().v4(),
productName: proName,
prodDesc: productDescription,
countInStock: count,
productPrice: price,
productImg: FieldValue.arrayUnion([imageUrls]),
}
]),
});
} catch (err) {
String errMsg = "error blahblah";
errorDialog(ctx!, errMsg);
}
notifyListeners();
}
for the uploadFile method i tried using images.forEach() instead of .map(), but it gave me void type error. uploadFile method:
Future<String> uploadFile(XFile _image) async {
var storageReference = storage
.ref()
.child('product_images')
.child(_currentUserOutletId!)
.child(Uuid().v4());
final metadata = SettableMetadata(
contentType: 'image/jpeg',
customMetadata: {'picked-file-path': _image.path},
);
if (kIsWeb) {
await storageReference.putData(await _image.readAsBytes(), metadata);
} else {
await storageReference.putFile(io.File(_image.path), metadata);
}
return await storageReference.getDownloadURL();
}
so, at the end only one image is uploaded and addProduct() does not add product to firestore database. log in android studio returns nothing. I couldn't find a method that would work with the xfile. help appreciated very much!
List<XFile> _imageFileList;
try{
final pickedFile = await _picker.pickMultiImage();
setState(() {
_imageFileList = pickedFile;
_imageFileList.forEach((element) async {
firebase_storage.FirebaseStorage storage = firebase_storage.FirebaseStorage.instance;
var date = DateTime.now().millisecondsSinceEpoch;
try {
setState(() {
_loading = true;
});
firebase_storage.UploadTask task = firebase_storage.FirebaseStorage.instance.ref('uploads/photos/'+date.toString()+'_image.png').putData(await element.readAsBytes(), SettableMetadata(contentType: 'image/jpeg'));
await storage.ref('uploads/file-to-upload.png').putData(await element.readAsBytes(), SettableMetadata(contentType: 'image/jpeg'));
firebase_storage.TaskSnapshot downloadUrl = (await task);
String url = (await downloadUrl.ref.getDownloadURL());
// print(url.toString());
} on FirebaseException catch (e) {
// e.g, e.code == 'canceled'
setState(() {
_loading = false;
});
}
});
try this way using image_picker plugin. You can get url after image upload and you have yo it in your data.
I am trying to upload multiple images to firebase storage at once. I can upload successfully but cannot retrieve the download URLs;
Future<void> saveImages() async {
int index = images.length;
setState(() {
isLoading = true;
});
try {
final ref = FirebaseStorage.instance
.ref()
.child('images/${FirebaseAuth.instance.currentUser!.uid}');
images.forEach((element) async {
final file = await element.file;
final refPut = ref.child('$element$index');
await refPut.putFile(
File(file!.path),
);
});
final ref2 = ref.child('${imagePciker.path.split('/')}');
await ref2.putFile(File(imagePciker.path));
final ListResult listData = await ref.listAll();
final data =await ref2.getDownloadURL();
print('Im HERE!=Line 95');
Future.forEach(listData.items, (Reference element) async {
await element.getDownloadURL().then((value) => listUrls.add(value));
print('line 101');
print(listUrls.length);
});
print('Line 104');
await FirebaseFirestore.instance.collection('test').add({
'titleDownloadUrl': data,
'ListOfDownloadUrl': listUrls,
});
print('Line 108');
setState(() {
isLoading = false;
});
} catch (e) {
/* setState(() {
isLoading = false;
}); */
print(e);
}
}
The print statements are to debug. This whole function returns and no errors are thrown.
However in the firebase collection 'test' the URLs are not stored correctly.
On the first/fresh run after restart of the app.
the array of ListOfDownloadUrl is empty
On a hot restart(with the no images saved in firebase storage)
the array of ListOfDownloadUrl has one URL
then on multiple restarts, the amount of URLs saved becomes huge(ie. 4 images uploaded-10 URLs saved).
Please comment if I need to add anything else;
Thanks for any Help
.forEach() is NOT ASYNCHRONOUS - it WILL NOT wait. Use await Promise.all(images.map()) (thus creating an array of promises, which must all resolve).
Solved!
Following the thinking of #LeadDreamer
The forEach isn't ASYNCHRONOUS, the problem with his answer is that flutter does not have
Promise.all()
What it does have if Future.wait(), which acts(in my case) the same way.
Future<void> saveImages() async {
int index = images.length;
setState(() {
isLoading = true;
});
try {
final refMain = FirebaseStorage.instance
.ref()
.child('images${FirebaseAuth.instance.currentUser!.uid}');
AssetEntity eleId =
new AssetEntity(id: '', typeInt: 5, width: 5, height: 5);
await Future.wait(images.map((element) async { <-- here instead of the for each
setState(() {
eleId = element;
});
final file = await element.file;
final refPut = refMain.child('suportImage$_counter/$element$index');
await refPut.putFile(
File(file!.path),
);
}));
final ref2 =
refMain.child('headingImage$_counter/${imagePciker.path.split('/')}');
await ref2.putFile(File(imagePciker.path));
final ListResult listData =
await refMain.child('suportImage$_counter').listAll();
final data = await ref2.getDownloadURL();
await Future.wait(listData.items.map((e) async { <-- here instead of for each
await e.getDownloadURL().then((value) => listUrls.add(value));
}));
i am use 'image_picker_web/image_picker_web.dart' in my app. Now when I choosed image, this image displayed, it's work. But when i try to save image in storage nothing happens.
Uint8List _image1;
Future getImg() async {
Uint8List tempImg = await ImagePickerWeb.getImage(asUint8List: true);
if (tempImg != null) {
setState(() {
// debugPrint(tempImg.toString());
_image1 = tempImg;
});
}}
save in storage:
void uploadImg() async {
final StorageReference productImg =
FirebaseStorage.instance.ref().child('ProductImg');
var timekey = DateTime.now();
final StorageUploadTask uploadTask =
productImg.child(timekey.toString() + 'jpg').putData(_image1);
var imageUrl = await (await uploadTask.onComplete).ref.getDownloadURL();
url = imageUrl.toString();
print('Image Url' + url);}
button:
RaisedButton(
onPressed: () {
uploadImg();
}
what am I doing wrong?
Give this a try:
final file = File.fromRawPath(uint8list);
final ref = FirebaseStorage.instance.ref().child("users/some_id/ProductImg.jpg");
final task = ref.putFile(file, StorageMetadata(contentType: "image/png"));
final snapshot = await task.onComplete;
if (snapshot.error != null) throw snapshot.error;
final downloadURL = await snapshot.ref.getDownloadURL();