Upload multiple file to fire store with progress bar in flutter - flutter

I would like to upload more than one file to fire-store while showing a progress indicator. Am trying to achieve this by looping over the files chosen by the user. The files are picked using the flutter filePicker package.
for (var file in choosenFiles) {
String fileName = file.name;
String? filePath = file.path;
File creatFile = File(filePath!);
UploadTask task = FirebaseStorage.instance
.ref('post_files/${value.id}-$fileName')
.putData(creatFile.readAsBytesSync());
task.snapshotEvents.listen((event) {
setState(() {
progress = ((event.bytesTransferred.toDouble() /
event.totalBytes.toDouble() *
100)
.roundToDouble());
});
});
}
for the progress indicator, i use a circularProgressIndicator to listen to the value of variable progress.
Center(
child: SizedBox(
height: 100,
width: 100,
child: CircularProgressIndicator(
value: progress / 100,
backgroundColor: Colors.green,
color: Colors.red,
strokeWidth: 8,
),
),
)
What could be the problem?. Will be grateful for any help. thanks.

Related

Dislaying Image File in Container Exported From Video

Trying to export a frame from my video file, save it to an image file list, and then display it back when building my list of containers.
setState(() async{
if (result!.files.isNotEmpty) {
for (PlatformFile item in result.files) {
videos.add(File(item.path!));
var duration = Duration(seconds: 1);
File image = await ExportVideoFrame.exportImageBySeconds(File(item.path!), duration, 0);
videoThumbs.add(image);
//tickets[widget.indexEvent].videos[i]
}
} else {}
});
Then later in my page class I am trying to display it back for the user in a child of my container:
Container(
width: 220,
height: 220,
color: colorPrimary,
child: Image.file(
videoThumbs[i],
width: 100,
height: 100,
fit: BoxFit.fill,
),
),
The code doesn't hard fail, and will build the apk, but when in the app, my thumbnail just says:
As you can see from my thumbnail, my list of photos and videos are building, but when it tries to loop through the videos and show a thumb, the array index is empty, I think? I believe I'm reading that error right.
I have seriously been at this for 2 weeks, and I could really use some help.
in this list, Your data is not complete, on 2 last of your data is null.
use this:
child:
videoThumbs[I] == null? const SizedBox():
Image.file(
videoThumbs[i],
width: 100,
height: 100,
fit: BoxFit.fill,
),

can't rebuild widget shown when downloading progress start flutter_downloader

Hi I'm trying to show different widget depending on the state of my attachment list
when not downloaded - download icon
when downloading in progress - circularprogressIcon / show the progress number
when done downloading - done icon
I manage to use the flutter_downloader and pass the data, but the problem is when we are still downloading the file, it didn't change to circular progress Icon it just stay in the download icon and suddenly when it's done the icon will be changed into done icon. How can I fix this ? I was able to print the progress on the terminal.
The problem is when i first attach the file, and then someone try to download it. It work just fine but when the other party delete it in their gallery and then tried to re-download it again, that's when the problem occur.
Here's my code:
progress == 0 ?
fileExistList[index] == true ?
Icon(
Icons.done,
color:
floatingActionButtonColor,
size: 19.0,
) : GestureDetector(
onTap: () async {
if (fileExistList[
index]) {
//Open file if it's already exist in the Local Path
OpenFile.open(externalDir!.path +
"/" +
fileAttachmentList[index]['name']);
} else {
currentDownload =
fileAttachmentList[index]['name'];
final taskId =
await FlutterDownloader.enqueue(
url: fileAttachmentList[index]['url'],
savedDir: externalDir!.path,
showNotification: true,
openFileFromNotification: true,
);
fileExistList[index] =
true;
}
},
child: Icon(
Icons.download,
color:
floatingActionButtonColor,
size: 17.0),
)
: currentDownload == fileAttachmentList[index]['name'] ?
progress == 100 ? Icon(
Icons.done,
color:
floatingActionButtonColor,
size: 19.0)
: Padding(
padding: EdgeInsets
.only(
right:
4),
child:
SizedBox(
child:
CircularProgressIndicator(
strokeWidth:
2.0,
valueColor:
AlwaysStoppedAnimation<Color>(
floatingActionButtonColor),
),
height:
10.0,
width:
10.0,
),
)
: fileExistList[index] == true
? Icon(
Icons.done,
color:
floatingActionButtonColor,
size: 19.0)
: Icon(
Icons
.download,
color:
floatingActionButtonColor,
size: 17.0)
I think you should go through the official docs. https://pub.dev/packages/flutter_downloader
There are callbacks for getting the updation status.

Firestore databse, upload and download files

I want to create button which will allow me to upload images to specific database collection, I manually created a collection and added some random pictures there which I'm using for slider in the app.
Here is code for fetching them from this database:
initSliderImages() async {
var result = await FirebaseFirestore.instance.collection('slider_images');
result.snapshots().listen((data) {
List imgs = [];
data.docChanges.forEach((change) {
var imageData = change.doc.data();
String image = imageData['url'];
imgs.add(CachedNetworkImage(fit: BoxFit.cover, imageUrl: image));
});
setState(() {
images = imgs;
});
});
}
And here is Slider code:
sList images = [];
Widget slider() {
return Container(
child: SizedBox(
height: 200.0,
width: fullWidth(context),
child: (images != null && images.length > 0)
? Carousel(
images: images,
dotSize: 3.0,
dotSpacing: 10.0,
dotColor: Colors.red,
indicatorBgPadding: 5.0,
dotBgColor: Colors.grey.withOpacity(0.5),
// dotBgColor: Colors.transparent,
borderRadius: true,
moveIndicatorFromBottom: 180.0,
noRadiusForIndicator: true,
)
: JumpingDotsProgressIndicator(
fontSize: 40.0,
color: Colors.blue,
),
),
);
}
So I want to create button which will alow me to upload images to this database collection, and also to alow me to remove them from database collection, maybe in some other page to create grid view which will display images from this database collection, and to be able to remove image from them.

Show picture from assets or from files Flutter

I want to show a picture inside a CircleAvatar, if the user never inserted a picture before then the default picture "empty_profile.png" will appear, otherwise if the user already inserted a picture from gallery or camera then the last one will be shown.
This is the code :
File _file = null;
File variable declared at the beginning.
Future<void> changeImage() async { //This will change the picture
File tmp = await imgFromGallery();
setState(() {
_file = tmp;
});
return;
}
The function above will change _file value to the file picked from gallery.
Widget myAvatar() {
return GestureDetector(
onTap: null,
child: CircleAvatar(
radius: 55,
backgroundColor: Color(0xffFDCF09),
child: CircleAvatar(
radius: 50,
child: Container(
child: _file == null
? AssetImage("empty_profile.png")
: FileImage(_file),
),
),
),
);
}
Finally if file is still null then the asset image is loaded, otherwise if a new picture is choosen then FileImage(_file) will show the picked image.
I have a lots of error because I don't know very well how to handle files, their paths and show images...Can you explain me how I should do?
To include static images in your Flutter project, place them inside the "assets/images" folder. Then, make sure to add this folder to your pubspec.yml:
flutter:
assets:
- assets/images/
Next, you may have errors related to trying to render an AssetImage inside a CircleAvatar. To render the file as an Image widget instead, use Image.asset(<path>). Your example could be written as:
Widget myAvatar() {
return GestureDetector(
onTap: null,
child: CircleAvatar(
radius: 55,
backgroundColor: Color(0xffFDCF09),
child: _file == null
? Image.asset("assets/images/empty_profile.png")
: _file
),
);
}
Finally, a great resource for user-selected images is the image_picker library: https://pub.dev/packages/image_picker. For example, a "Select from Gallery" button could invoke the following code, which allows the user to crop the image and saves it as an Image widget:
PickedFile image = await picker.getImage(
source: ImageSource.gallery, // to select from camera, use ImageSource.camera
maxHeight: 1024,
maxWidth: 1024,
imageQuality: 50
);
try {
File croppedImage = await ImageCropper.cropImage( // use platform-native image cropping
sourcePath: image.path,
cropStyle: CropStyle.circle,
maxWidth: 512,
maxHeight: 512
);
setState(() { // refresh state to render new profile image
_file = Image.file(croppedImage)
})
} catch (err) {
print(err)
}
You can use CachedNetworkImage PlugIn - Update other details as per your need. This code show Network Images, if not available will show Assets Image.
new Container(
width: 140.0,
height: 140.0,
child: ClipOval(
child: CachedNetworkImage(
imageUrl: _profile == null ? "" : Api.baseURL + _profile,
placeholder: (context, url) =>
Center(child: CircularProgressIndicator()),
errorWidget: (context, url, error) => Image.asset(
"img/user.png",
fit: BoxFit.cover,
height: 140.0,
width: 140.0,
),
fit: BoxFit.cover,
height: 140.0,
width: 140.0,
),
),
),

flutter, trying to update a picture from Storage

I'm trying to upload, and update a picture from firebase storage. But for some reason this is not working properly.
This would be the scenario; A user take a picture from his camera, so this picture is uploaded to my storage, so after that I get the url picture, so I can use this like NetworkImage(url) to update the picture.
This is what's happening currently:
Let's say I don't have any picture.
I update my profile with a new picture. (This works perfectly).
Now let's say I want to update my profile picture, so I take another picture, let's call it A so I upload this one.
Nothing happens, picture doesn't change.
But If I try again with a B picture, for some reason the picture is updated with the A picture.
This would be my code and how I'm facing this feature.
I have the next method which is invoked when a user click over his picture. I wait for the result (value) so when I got the result I upload the picture. Then, when the picture is uploaded, I just call to setState and save the url into the _imageUrl variable.
After that, I change the "profilePic" attribute from my data base to true.
String _imageUrl = 'assets/profileDefault.jpg';
bool profilePicture = false;
io.File profilePic;
Future getFromCamara() async {
await ImagePicker().getImage(source: ImageSource.camera).then((value) {
profilePic = io.File(value.path);
FirebaseStorage.instance.ref().child('picture').putFile(profilePic);
}).then((result) {
var ref = FirebaseStorage.instance.ref().child('picture');
ref.getDownloadURL().then((loc) => setState(() => _imageUrl = loc));
});
try {
FirebaseFirestore.instance
.collection('Usuarios')
.doc(uid)
.update({'profilePic': true});
} catch (e) {
print(e.toString());
}
So now, using a StreamBuilder, I get the result of profilePic from my DataBase, if is True, I download the URL, and if don't, I just use the Asset default's pic.
body: StreamBuilder(
stream: FirebaseFirestore.instance.collection('Usuarios').snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot1) {
if (!snapshot1.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
List<DocumentSnapshot> users = snapshot1.data.docs;
for (DocumentSnapshot user in users) {
if (user.id == userID) {
profilePicture = user['profilePic'];
}
}
if (profilePicture) {
FirebaseStorage.instance
.ref()
.child('picture')
.getDownloadURL()
.then((loc) => _imageUrl = loc);
} else {
_imageUrl = 'assets/profileDefault.jpg';
}
return Stack(
alignment: Alignment.center,
children: <Widget>[
Positioned(
top: 0,
child: Container(
color: Color.fromRGBO(255, 0, 0, 70),
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * .55,
),
),
Positioned(
top: MediaQuery.of(context).size.height * .015,
left: 15,
right: 15,
child: Container(
width: MediaQuery.of(context).size.height * .90,
height: 300,
padding: EdgeInsets.only(bottom: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTap: () => _setPic(context),
child: CircleAvatar(
radius: 79,
backgroundColor: Color(0xFFFFFFFFF),
child: CircleAvatar(
radius: 75,
backgroundImage: profilePicture
? NetworkImage(_imageUrl)
: AssetImage(_imageUrl),
),
),
),
// More code...
What I'm doing wrong? Why my picture isn't getting updated?
Updated:
I tried this, so I can save in pictureTemp the picture's bytes, calling to setState to rebuild the widget and put the picture with Image.memory(pictureTemp). But it doesn't seem to work.
Uint8List pictureTemp;
io.File profilePic;
Future getFromCamara() async {
var pickedFile = await ImagePicker().getImage(source: ImageSource.camera);
var image = await pickedFile.readAsBytes();
FirebaseStorage.instance
.ref()
.child('picture')
.putFile(io.File(pickedFile.path));
setState(() {
pictureTemp = image;
});
child: CircleAvatar(
radius: 75,
backgroundImage: profilePicture
? pictureTemp == null
? AssetImage(_imageUrl)
: Image.memory(pictureTemp)
: AssetImage(_imageUrl),
),
Here when the image is picked you should directly set it or you can set it after the firebase upload is finished successfully.
But rather than loading an image from Firebase URL after the upload, you can directly load from the picked file as follows;
image = Image.memory(await pickedFile.readAsBytes())
This will instantly set the image and will save you a read call to Firebase. You should always try to minimize the Firebase Reads whenever possible.