Flutter Firestore Storage get downloadUrl - firebase

I need to get the downloadURL from uplaoding a photo to a Firebase Storage so I can store it inside of a Firestore document. The issue with my code is that the URL that is saved isnt a https//: so I need to get the downloadURL. I was wondering where I need to call it to get the downloadUrl and save it inside of my Firestore Database.
Here is my code:
Future<void> _uploadProfilePhoto(String inputSource) async {
final picker = ImagePicker();
PickedFile? pickedImage;
try {
pickedImage = await picker.getImage(
source: inputSource == 'camera'
? ImageSource.camera
: ImageSource.gallery,
maxWidth: 1920);
final String fileName = path.basename(pickedImage!.path);
File imageFile = File(pickedImage.path);
try {
await storage.ref("avatars/$fileName").putFile(
imageFile,
SettableMetadata(customMetadata: {
'uploaded_by': '$uid',
}));
// Create/Update firesotre document
users.doc(uid).update({
"profilePhoto": fileName,
});
setState(() {});
} on FirebaseException catch (error) {
print(error);
}
} catch (err) {
print(err);
}
}

You can call getDownloadURL() on the reference at any time after the file upload has completed. So this would be a good spot:
await storage.ref("avatars/$fileName").putFile(
imageFile,
SettableMetadata(customMetadata: {
'uploaded_by': '$uid',
}));
var downloadURL = await storage.ref("avatars/$fileName").getDownloadURL();
// Create/Update firesotre document
users.doc(uid).update({
"profilePhoto": downloadURL,
});

Related

Is there any way to save flutter_tts file to firebase storage?

I am working on a flutter project in which user is supposed to create some scripts and by typing them in text and then flutter_tts library is supposed to convert them to audio file which works fine for that time being but I want to save that file into firebase storage for later user. I have tried the following code but it just saves blank audio file in the firebase storage. Any kind of help will be appreciated.
The code I have tried is:
final FlutterTts _flutterTts = FlutterTts();
late var fileName;
/// creation of audio script
Future createAudioScript(
String name,
String script,
String firebasepath,
) async {
await _flutterTts.setLanguage("en-US");
await _flutterTts.setSpeechRate(1.0);
await _flutterTts.setVolume(1.0);
await _flutterTts.setPitch(1.0);
await _flutterTts.setVoice(
{"name": "en-us-x-tpf-local", "locale": "en-US"},
);
await _flutterTts.speak(script);
fileName = GetPlatform.isAndroid ? '$name.wav' : '$name.caf';
print('FileName: $fileName');
var directoryPath =
"${(await getApplicationDocumentsDirectory()).path}/audio/";
var directory = Directory(directoryPath);
if (!await directory.exists()) {
await directory.create();
print('[INFO] Created the directory');
}
var path =
"${(await getApplicationDocumentsDirectory()).path}/audio/$fileName";
print('[INFO] path: $path');
var file = File(path);
if (!await file.exists()) {
await file.create();
print('[INFO] Created the file');
}
await _flutterTts.synthesizeToFile(script, fileName).then((value) async {
if (value == 1) {
print('generated');
var file = File(
'/storage/emulated/0/Android/data/com.solution.thriving/files/$fileName',
);
print(file);
moveFile(file, path, '$firebasepath/$fileName').then((value) {
print('move file: $value');
_app.link.value = value;
print('link: ${_app.link.value}');
});
}
});
}
/// move file from temporary to local storage and save to firebase
Future<String> moveFile(
File sourceFile,
String newPath,
String firebasePath,
) async {
String audioLink = '';
print('moved');
await sourceFile.copy(newPath).then((value) async {
print('value: $value');
await appStorage.uploadAudio(value, fileName, firebasePath).then((audio) {
print(audio);
audioLink = audio;
return audioLink;
});
}).whenComplete(() async {
customToast(message: 'Audio has been generated successfully.');
});
return audioLink;
}
After spending whole day and with the help of a friend, I finally managed to figure out the issue which was being caused because I was using synthesizeToFile() and speak() functions at the same time, which I managed to resolved the issue by changing my code to the following code snippet.
final FlutterTts _flutterTts = FlutterTts();
late var fileName;
/// converting text to speech
Future createAudioScript(
String name,
String script,
String firebasepath,
) async {
await _flutterTts.setLanguage("en-US");
await _flutterTts.setSpeechRate(1.0);
await _flutterTts.setVolume(1.0);
await _flutterTts.setPitch(1.0);
await _flutterTts.setVoice(
{"name": "en-us-x-tpf-local", "locale": "en-US"},
);
if (GetPlatform.isIOS) _flutterTts.setSharedInstance(true);
// await _flutterTts.speak(script);
fileName = GetPlatform.isAndroid ? '$name.wav' : '$name.caf';
log('FileName: $fileName');
await _flutterTts.synthesizeToFile(script, fileName).then((value) async {
if (value == 1) {
log('Value $value');
log('generated');
}
});
final externalDirectory = await getExternalStorageDirectory();
var path = '${externalDirectory!.path}/$fileName';
log(path);
saveToFirebase(path, fileName, firebasPath: '$firebasepath/$name')
.then((value) => {log('Received Audio Link: $value')});
}
/// saving converted audio file to firebase
Future<String> saveToFirebase(String path, String name,
{required String firebasPath}) async {
final firebaseStorage = FirebaseStorage.instance;
SettableMetadata metadata = SettableMetadata(
contentType: 'audio/mpeg',
customMetadata: <String, String>{
'userid': _app.userid.value,
'name': _app.name.value,
'filename': name,
},
);
var snapshot = await firebaseStorage
.ref()
.child(firebasPath)
.putFile(File(path), metadata);
var downloadUrl = await snapshot.ref.getDownloadURL();
print(downloadUrl + " saved url");
return downloadUrl;
}

How to add Flutter Firebase VIdeo Upload Progrese Indecator | Upload Progress Indicator |

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");

Flutter Firebase Storage 0.5.0 upload file and video error

What I want to do: Upload a file and a video with Firebase Storage 0.5.0 and return url.
What current problem is: I can upload file and image with Firebase storage 0.5.0, but I can't return url. I also see my file and video uploaded in Firebase storage in Firebase console.
My code:
Future<String> _uploadFile(Reference ref, File file,
[SettableMetadata metadata]) async {
UploadTask uploadTask = ref.putFile(file, metadata);
uploadTask.whenComplete(() async {
try {} catch (onError) {
print("Error");
}
});
final url = await ref.getDownloadURL();
return url;
}
Future<String> uploadVideo(File video,
{String refName, SettableMetadata metadata}) async {
metadata = SettableMetadata(contentType: 'video/mp4');
final name = refName != null ? refName : path.basename(video.path);
final ref = _VideoRef.child(name);
return _uploadFile(ref, video, metadata);
}
Future<File> downloadImage(String imageUrl, String savePath) async {
final ref = _storage.ref(imageUrl);
var file = File(savePath);
await ref.writeToFile(file);
return file;
}
What the console told me:
FirebaseException (Firebase_storage/object-not-found). No object exist in desired reference.
How do I fix this?
Try the following:
uploadTask.whenComplete(() async {
try {
url = await ref.getDownloadURL();
} catch (onError) {
print("Error");
}
});
When the future completes, call getDownloadURL() to get the url.

how to get image URL form firebase storage to firestore

i am trying to upload the image to firebase and get the URL in firestore. It does upload the image but it does not get the URL to Firestore.
this is how i get the image.
Future getImage1() async {
// ignore: deprecated_member_use
var firstImage = await ImagePicker.pickImage(
source: ImageSource.gallery, imageQuality: 65);
setState(() {
_image1 = firstImage;
});
}
this is how i upload and get the url.
uploadPic() async {
Reference ref = storage.ref().child("image1" + DateTime.now().toString());
UploadTask uploadTask = ref.putFile(_image1);
uploadTask.then((res) {
String url = res.ref.getDownloadURL().toString();
imageUrl1 = url;
return url;
});
}
this is how i get the link in firestore
"image 1 Url":(_image1 != null) ? await uploadPic() : null,
getDownloadURL is a Future, so how about you try it like this:
Future<String> uploadPic() async {
Reference ref = storage.ref().child("image1" + DateTime.now().toString());
UploadTask uploadTask = ref.putFile(_image1);
String url;
await uploadTask.whenComplete(() {
res.ref.getDownloadURL().then((fileUrl){
url = fileUrl as String;
});
});
return url;
}

Upload multi images to firestore using flutter and get it's download URLs and save all of URLs to firebase

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.

Resources