How to upload a video picked from user into firebase? - flutter

Im trying to upload a video into firebase .But theres a problem ,the more videos I upload, the more space a video needs. Im only uploading one video the same time . The video is picked from user . And when user picked the first video and when video duration is about 2 seconds long, it gets very fast uploaded. Then on the next also 2 or 3 seconds duration it takes a bit more time then the first but still ok . And then like on the 4 video ,its need very much time. And the video ist again 2 or 3 seconds recording but storage like 13 minutes . And im not getting why. This only is resolved when im using a new android emulator. it dont care when im deleting all data from firebase and like recording the first video into it .
Hope anyone can example why this error happen.
Heres my code
final allvideos = FirebaseStorage.instance.ref().child('allvideos');
final allimages = FirebaseStorage.instance.ref().child('allimages');
uploadVideo() async {
setState(() {
isuploading = true;
});
try {
var firebaseuseruid = FirebaseAuth.instance.currentUser.uid;
DocumentSnapshot userdoc = await FirebaseFirestore.instance
.collection('meinprofilsettings')
.doc(firebaseuseruid)
.get();
var alldocs = await FirebaseFirestore.instance.collection('videos').get();
int length = alldocs.docs.length;
String videourl = await uploadvideotostorage("Video $length");
String previewimage = await uploadimagetostorage("Video $length");
FirebaseFirestore.instance.collection('videos').doc("Video $length").set({
'username': userdoc.data()['username'],
'uid': firebaseuseruid,
'profilepic': userdoc.data()['url'],
'id':"Video $length",
'likes': [],
'commentcount': 0,
'sharecount': 0,
'hashtag1': hashtagcontroller.text,
'hashtag2': hashtagcontroller2.text,
'hashtag3': hashtagcontroller3.text,
'videourl': videourl,
'previewimage': previewimage,
'ratings': [],
});
Navigator.pop(context);
} catch (e) {
print(e.toString());
}
}
}
Heres how I upload it
the picture is for preview picture
getpreviewimage() async {
final previewimage = await flutterVideoCompress.getThumbnailWithFile(
widget.videopath_asstring,
);
return previewimage;
}
compressvideo() async {
if (widget.imageSource == ImageSource.gallery) {
return widget.videofile;
} else {
final compressvideo = await flutterVideoCompress.compressVideo(
widget.videopath_asstring,
quality: VideoQuality.MediumQuality);
return File(compressvideo.path);
}
}
uploadvideotostorage(String id) async {
final video = await allvideos.child(id).putFile(await compressvideo());
String url = await video.ref.getDownloadURL();
return url;
}
uploadimagetostorage(String id) async {
final video = await allimages.child(id).putFile(await getpreviewimage());
String url = await video.ref.getDownloadURL();
id=url;
return url;
}

Use something like this to generate your random ID:
import 'dart:math';
import 'package:intl/intl.dart';
String generateId() {
int randomNumber = Random().nextInt(9999999);
String now = DateTime.now().millisecondsSinceEpoch.toString().substring(7);
String formatted = DateFormat('MMdh').format(DateTime.now());
return randomNumber.toString() + formatted + now;
}
Change your upload function to look like this:
Future<String> uploadvideotostorage(String id) async {
final video = await allvideos.child(id).putFile(await compressvideo());
String url = await video.ref.getDownloadURL();
return url;
}
When you create a video, assign it a random id like this:
String randomlyGeneratedId = generateId();
Finally, to get your download URL back:
String finalVideoURL = await uploadvideotostorage(randomlyGeneratedId);

Related

how to handle the time lag after capturing the image ImagePicker Flutter

im learning flutter and now tried to capture the photo with ImagePicker package from the following method, but after I successfully capture the photo, there is always 1 sec until app get the data and jump to next page:
Future pickImage(ImageSource source) async {
try {
var image = await ImagePicker().pickImage(source: source);
if (image == null) return;
final imagePermanent = await saveImagePermanently(image.path);
selectedImage = File(imagePermanent.path);
isUploaded.value = !isUploaded.value;
update();
} on PlatformException catch (e) {
print('Failed to pick image: $e');
}
}
Future<File> saveImagePermanently(String imagePath) async {
final directory = await getApplicationDocumentsDirectory();
final name = basename(imagePath);
final image = File('${directory.path}/$name');
return File(imagePath).copy(image.path);
}
now my solution is adding a listener onInit when image is created with GetX:
#override
void onInit() {
super.onInit();
ever(isUploaded, (value) {
Get.to(
() => AddPersonProfileAddDetails(),
);
});
}
So is there a way to detect the status of capturing the image like finished/failed/progressing, thanks for any clue or let me know a better way to jump to next page after capturing the image, thanks a lot!

Image URL from firebase storage to firestore

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());
});
}

PlatformException error, Invalid document reference, When attempting to work with Firebase Storage

I have created a function to work on my app. This function add's the photo from my camera or gallery into the Firebase storage, and into the user collection. Althought I'm receiving a strange error when trying to add the data. I have attempted to pass throught this Exception but the data wasn't added neither.
The erro:
This is the function:
class Product {
final Firestore firestore = Firestore.instance;
final FirebaseStorage storage = FirebaseStorage.instance;
DocumentReference get firestoreRef => firestore.document('products/$id');
StorageReference get storageRef => storage.ref().child('products').child(id);
Future<void> save() async {
loading = true;
final Map<String, dynamic> data = {
'name': name,
'description': description,
'sizes': exportSizeList()
};
if (id == null) {
final doc = await firestore.collection('products').add(data);
id = doc.documentID;
} else {
await firestoreRef.updateData(data);
}
final List<String> updateImages = [];
for (final newImage in newImages!) {
if (images.contains(newImage)) {
updateImages.add(newImage as String);
} else {
final StorageUploadTask task =
storageRef.child(Uuid().v1()).putFile(newImage as File);
final StorageTaskSnapshot snapshot = await task.onComplete;
final String url = await snapshot.ref.getDownloadURL() as String;
updateImages.add(url);
}
}
for (final image in images) {
if (!newImages!.contains(image)) {
try {
final ref = await storage.getReferenceFromUrl(image);
await ref.delete();
} catch (e) {
debugPrint('Falha ao deletar $image');
}
}
}
await firestoreRef.updateData({'images': updateImages});
images = updateImages;
loading = false;
}
}
From the error message is looks like id doesn't have a value in this call:
firestore.document('products/$id');
When id has no value, that leads to a document reference with a path /products/, which explains the error message.
So you'll want to run the code in a debugger, set a breakpoint on that line, and figure out why id doesn't have a value at that point.

Flutter user data taking up a lot of space

My flutter app user data takes up a lot of space. I'm currently using the following code to save the user data
class FileUtil {
static Future<String> get getFilePath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
static Future<File> get getFile async {
final path = await getFilePath;
return File('$path/user.txt');
}
static Future<File> saveToFile(String data) async {
final file = await getFile;
return file.writeAsString(data);
}
static Future readFromFile() async {
try {
final file = await getFile;
String fileContents = await file.readAsString();
log(fileContents);
return json.decode(fileContents);
} catch (e) {
return "";
}
}
String formatData() {
String formattedString;
Map x = {};
x['a'] = a;
// other variables
formattedString = json.encode(x);
return formattedString;
}
void saveData() async {
try {
await saveToFile(formatData());
//print('DATA SAVED');
} catch (e) {
//print('Could not save data due to: $e');
}
}
}
Whenever the user interacts with something in the app that needs to be saved, I run saveData(). This happens quite often in my app. However, after using the app for a while, the user data can jump to a few hundred MB. I've used a JSON calculator to estimate the space of the formatData() output string and it's much less than 1MB. What should I do to minimise user data?

Firebase Dynamic Links in flutter seems to recognize it was opened through a link but the link is always null

I'm using dynamic links ^0.7.0+1
When I press the link it loads the app, but doesn't navigate to the page I wanted, I've printed the link I receive, and it's always null, both when the app is in the background or not running at all.
Future<void> retrieveDynamicLink(BuildContext context) async {
List<String> linkData;
print('in retrieve link');
final PendingDynamicLinkData data =
await FirebaseDynamicLinks.instance.getInitialLink();
_handleDynamicLink(data);
FirebaseDynamicLinks.instance.onLink(
onSuccess: (PendingDynamicLinkData dynamicLink) async {
linkData = await _handleDynamicLink(dynamicLink);
}, onError: (OnLinkErrorException e) async {
print('onLinkError');
print(e.message);
});
if (data != null) {
AppRoutes.pushLinkEntryPage(
context: context, spreadsheetId: linkData[0], grade: linkData[1]);
}
}
static Future<List<String>> _handleDynamicLink(
PendingDynamicLinkData data) async {
String ssId = '';
String grade = '';
final Uri deepLink = data?.link;
print('deepLink = $deepLink');
if (deepLink == null) {
return null;
}
if (deepLink.queryParameters.containsKey('ss')) {
ssId = deepLink.queryParameters['ss'];
print('in retrieve link: ssID = $ssId');
}
if (deepLink.queryParameters.containsKey('gd')) {
grade = deepLink.queryParameters['gd'];
print('in retrieve link: gd = $grade');
}
return [ssId, grade];
}
I wasted couple of hours on this, and found the fix to be using the "Long dynamic link" instead of the "Deep link".
See attached image below:(This show details of the dynamic link in console)