I am having trouble in creating a progress bar to indicate the process of me uploading an image to firebase storage.
Future getImage(BuildContext context) async {
final picker = ImagePicker();
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
_image = File(pickedFile.path);
});
StorageReference firebaseStorageRef = FirebaseStorage.instance.ref().child('profile/${Path.basename(_image.path)}}');
StorageUploadTask uploadTask = firebaseStorageRef.putFile(_image);
var dowurl = await (await uploadTask.onComplete).ref.getDownloadURL();
setState(() {
_imageURL = dowurl.toString();
});
print(_imageURL);
}
This is the code that I have written to upload the image and getting the image URL.
Hope someone can help me up thanks!
you can listen to the events on your uploadTask.
Here:
uploadTask.events.listen((event) {
setState(() {
_progress = event.snapshot.bytesTransferred.toDouble() /
event.snapshot.totalByteCount.toDouble();
});
}).onError((error) {
// do something to handle error
});
Now you can just display the progress like this:
Text('Uploading ${(_progress * 100).toStringAsFixed(2)} %')
To create a progress bar:
LinearProgressIndicator(
value: _progress,
)
Hope that helps.
The answer by Ayush Shekhar is correct, but outdated on some parts due to the rapid updating on firebase plugins.
On top of state class
double? _progress;
...
In the upload method, you can setup like this.
uploadTask.snapshotEvents.listen((event) {
setState(() {
_progress =
event.bytesTransferred.toDouble() / event.totalBytes.toDouble();
print(_progress.toString());
});
if (event.state == TaskState.success) {
_progress = null;
Fluttertoast.showToast(msg: 'File added to the library');
}
}).onError((error) {
// do something to handle error
});
You can get the download link like this.
uploadTask.then((snap) async {
final downloadURL = await snap.ref.getDownloadURL();
print(downloadURL);
});
...
Use the _progress in UI like this.
if (_progress != null)
LinearProgressIndicator(
value: _progress,
minHeight: 2.0,
color: Constants.primaryColor,
),
Use Future Builder and pass this getImage inside future builder Future Builder Example
or You can use Modal Progress HUD
Check this, it will work for both video and images:
final fil = await ImagePicker().pickVideo(source: ImageSource.gallery);
final file = File(fil!.path);
final metadata = SettableMetadata(contentType:"video/mp4");
final storageRef = FirebaseStorage.instance.ref();
final uploadTask = storageRef
.child("images/path/to/video")
.putFile(file, metadata);
// Listen for state changes, errors, and completion of the upload.
uploadTask.snapshotEvents.listen((TaskSnapshot taskSnapshot) {
switch (taskSnapshot.state) {
case TaskState.running:
final progress =
100.0 * (taskSnapshot.bytesTransferred / taskSnapshot.totalBytes);
print("Upload is $progress% complete.");
break;
case TaskState.paused:
print("Upload is paused.");
break;
case TaskState.canceled:
print("Upload was canceled");
break;
case TaskState.error:
// Handle unsuccessful uploads
break;
case TaskState.success:
print("Upload is completed");
// Handle successful uploads on complete
// ...
break;
}
});
Related
I am very new to Dart, and coding in general. I have produced this code after watching tutorials on YouTube. For the most part, I have been able to troubleshoot most of my problems on my own, here I feel I need some help. I have written code to upload photographs, but it is giving the following error. Please help me understand this.
I/flutter ( 7512): [firebase_storage/object-not-found] No object exists at the desired reference.
My code is here:-
Future uploadImagetoFB() async {
if (_image != null) {
try{
String fileName = Path.basename(_image.path);
print('The uploaded file name is: ${fileName}');
final Reference storageReference =
FirebaseStorage.instance.ref().child('profileImages');
_imageUrl = await storageReference.getDownloadURL();
print('The Image Url: $_imageUrl');
} catch (e){
print(e);
}
}
}
Future PickedImage(ImageSource source) async {
try {
final image = await ImagePicker()
.pickImage(source: source, maxWidth: 160, maxHeight: 160);
if (image == null) return;
setState(() {
_image = File(image.path);
});
uploadImagetoFB();
} on PlatformException catch (e) {
print('failed to Upload ');
}
}
To upload photos to Firebase, use the code below.
This is the string where I set the image URL :
String? url;
Code for image upload:
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);
int uploadTimestamp = DateTime.now().millisecondsSinceEpoch;
if (image != (null)) {
Reference ref =
_firebaseStorage.ref().child('profileImages/$uploadTimestamp');
UploadTask uploadTask = ref.putFile(file);
var imageUrl = await (await uploadTask).ref.getDownloadURL();
setState(() {
url = imageUrl.toString();
});
} else {
print('No Image Path Received');
}
} else {
print('Permission not granted. Try Again with permission access');
}
}
Result of Firebase :
Profile Images folder :
Uploaded image :
how I can add multiple images and store them in an array in firebase ?
every container has a + button so the user can add single image per container then I WANT TO STORE them in my firebase
any help would be greatly appreciated ^^
what you are showing in your image is fbCloudStore which is use to store information in json structure.
To store the images you may use fbStorge.
here's an snippet I use on my project:
Future<String?> uploadFile({
required FilePickerResult file,
required String fileName,
required FirebaseReferenceType referenceType,
}) async {
try {
final ref = _getReference(referenceType);
final extension = path.extension(file.files.first.name);
final _ref = ref.child(fileName + extension);
late UploadTask uploadTask;
if (kIsWeb) {
uploadTask = _ref.putData(file.files.first.bytes!);
} else {
uploadTask = _ref.putFile(File(file.files.single.path!));
}
var url;
await uploadTask.whenComplete(
() async => url = await uploadTask.snapshot.ref.getDownloadURL());
print(url);
return url;
} on FirebaseException catch (_) {
print(_);
}
}
Note that I'm returning the URL of fbStorage in order to associate it with fbCloudStorage
final url =
await FirebaseStorageSer.to.uploadFile(
file: result,
fileName: STORAGE_USER_PROFILE_PICTURE,
referenceType: FirebaseReferenceType.user,
);
if (url != null) {
await FirebaseAuthSer.to
.updateUserProfile(photoUrl: url);
}
FirebaseReferenceType.user is just a simple enum to simplify ref targets.
How to add Flutter Firebase VIdeo Upload Progrese Indecator | Upload Progress Indicator |
Anyone can help me
MediaInfo compressVideo = await VideoCompress.compressVideo(
videoPath,
quality: VideoQuality.Res640x480Quality,
includeAudio: true,
);
print('video Compressing Done');
var uploadVideo = await FirebaseStorage.instance
.ref()
.child("videos/${Me.get().uid}/${videoDoc.id}")
.putFile(File(compressVideo?.path));
print('video Uploading Done');
final videoUrl = await uploadVideo.ref.getDownloadURL();
showToast("Upload Successful");
This should be a good example from it:
Future<void> handleTaskExample2(String filePath) async {
File largeFile = File(filePath);
firebase_storage.UploadTask task = firebase_storage.FirebaseStorage.instance
.ref("videos/${Me.get().uid}/${videoDoc.id}")
.putFile(File(compressVideo?.path));
task.snapshotEvents.listen((firebase_storage.TaskSnapshot snapshot) {
print('Task state: ${snapshot.state}');
print(
'Progress: ${(snapshot.bytesTransferred / snapshot.totalBytes) * 100} %');
}, onError: (e) {
// The final snapshot is also available on the task via `.snapshot`,
// this can include 2 additional states, `TaskState.error` & `TaskState.canceled`
print(task.snapshot);
if (e.code == 'permission-denied') {
print('User does not have permission to upload to this reference.');
}
});
// We can still optionally use the Future alongside the stream.
try {
await task;
print('Upload complete.');
} on firebase_core.FirebaseException catch (e) {
if (e.code == 'permission-denied') {
print('User does not have permission to upload to this reference.');
}
// ...
}
}
I would also recommend to check the docs for more details.
finally, I'm getting the right answer.
This answer is perfectly works in my case.
//This is the document reference
Reference videoRef = FirebaseStorage.instance
.ref()
.child("videos/${Me.get().uid}/${videoDoc.id}");
//Here video is uploading and return UploadTask
UploadTask videoTask = videoRef.putFile(compressVideo.file);
//This is upload task StreamSubscription
final StreamSubscription<void> streamSubscription =
videoTask.snapshotEvents.listen((data) {
double uploadPer;
setState(() => uploadPer = (data.bytesTransferred / data.totalBytes)*
100);
print(uploadPer);
});
//When video uploading is completed then streamSubscription is cancel.
await videoTask.whenComplete(() => null);
streamSubscription.cancel();
//This is finally get video download URL
final String videoUrl = await videoRef.getDownloadURL();
print(videoUrl);
showToast("Upload Successful");
Here is my challenge:
I'm using the following method to select multiple images from my phone gallery (package multi_image_picker:needs to be added in pubspec.yaml)
Future<void> loadAssets() async {
List<Asset> resultList = <Asset>[];
String error = 'No Error Detected';
try {
resultList = await MultiImagePicker.pickImages(
maxImages: 300,
enableCamera: true,
selectedAssets: images,
cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
materialOptions: MaterialOptions(
actionBarColor: "#abcdef",
actionBarTitle: "Example App",
allViewTitle: "All Photos",
useDetailsView: false,
selectCircleStrokeColor: "#000000",
),
);
for (int i = 0; i < resultList.length; i++) {
print('resultList[i].name: ${resultList[i].name}');
}
} on Exception catch (e) {
error = e.toString();
}
if (!mounted) return;
setState(() {
images = resultList;
_error = error;
});
}
My variable resultListstores instances of Assets. I would like to upload those assets to a certain path in my FirebaseStorage.
In the past, I was using the package image_picker: which allowed me to select only one image from my phone gallery. But the image_picker could store the selected images as Type of File instead of Assets and from the Type of File I'm able to get the image-path which I could use to upload the image to my FirebaseStorage.
But I have no clue how to upload the Assets getting from the method loadhAssets() to my FirebaseStorage.
Anyone has an idea how to solve that?
I hope my concern was clear enough.
Many thanks in advance :)
The image_picker package also allows you to pick multiple images, not just one. I have a sample implementation code here:
List<XFile> selectedImages = [];
Future<void> pickImages() async {
final pickedFileList = await ImagePicker().pickMultiImage();
if (pickedFileList != null) {
setState(() {
selectedImages = pickedFileList;
});
}
}
And here's how you can upload your selected images to Firebase Storage:
FirebaseStorage storage = FirebaseStorage.instance;
Reference storageRef = storage.ref();
List<String> imgURL = []; //to store url of uploaded images
Future<void> uploadSelectedImages() async {
for (var i = 0; i < selectedImages.length; i++) {
final ref = storageRef.child('Photos/image$i');
await ref.putFile(File(selectedImages[i].path)).whenComplete(() async {
await ref.getDownloadURL().then((value) { //upload and get URL
setState(() {
imgURL.add(value);
});
});
});
}
}
Hope this help!
I have a form that have images to upload , when the user try to press on "Submit" button i'm trying to upload list of images to firestore and get all of its URLs and then submit a form to "x" collection in firebase but the writing on "x" collocation done before upload the images and get it's URLs.
I thinks the problem with (async,await).
Appreciate to help me.
List<File> imagePaths= new List() ;
List<String> imageURL= new List() ;
Future<FirebaseUser> getUser() async {
return await _auth.currentUser();
}
Future<void> uploadPic(File _image) async {
String fileName = basename(_image.path);
StorageReference firebaseStorageRef =
FirebaseStorage.instance.ref().child(Random().nextInt(10000).toString()+fileName);
StorageUploadTask uploadTask = firebaseStorageRef.putFile(_image);
var downloadURL = await(await uploadTask.onComplete).ref.getDownloadURL();
var url =downloadURL.toString();
imageURL.add(url); // imageURL is a global list that suppose to contain images URLs
print("\n ---------------------------\n downloadURL :"+ url);
print("\n ---------------------------\n imageURL :"+ imageURL.toString());
}
Submit(BuildContext context) {
//imagePaths is list of file
imagePaths.add(Front_image);
imagePaths.add(Back_image);
imagePaths.forEach((x) => {
uploadPic(x)
});
getUser().then((user) {
crudObj.addNew({
'uid': user.uid,
'name': name,
'images':imageURL,
}).then((result) {
Navigator.pop(context);
}).catchError((e) {
print(e);
});
});
}
You should call your Submit only once your upload task is complete. I would recommend implementing something like this:
Stream uploadImageToFirebaseStorage(File image, String fullPath) {
final StorageReference firebaseStorageRef =
FirebaseStorage.instance.ref().child(fullPath);
StorageUploadTask task = firebaseStorageRef.putFile(image);
return task.events;
}
And then listen to this Stream and only then submit:
uploadImageToFirebaseStorage(
image, 'path/imagename.jpg'
).listen((data) async {
StorageTaskEvent event = data;
if (data.type == StorageTaskEventType.success) {
String downloadUrl = await event.snapshot.ref.getDownloadURL();
await Submit(title, imageUrl: downloadUrl);
return true;
}
if (data.type == StorageTaskEventType.failure) return false;
});
Please take note that I did not re-write your code, I am sharing a possible implementation.