Future<void> _loadFileContent() async {
final file = File(widget.filePath);
final extension = file.path.split('.').last.toLowerCase();
if (extension == 'pdf') {
final pdf = await PDFDoc.fromFile(file);
final pages = await pdf.pages;
final texts = await Future.wait(pages.map((page) => page.text));
_fileContent = texts.join('\n');
} else if (extension == 'txt') {
_fileContent = await file.readAsString();
// var decoded = base64.decode( _fileContent);
} else if (extension == 'docx') {
} else {
throw Exception('Unsupported file extension: $extension');
}
setState(() {
_isLoading = false;
});
How to Read a docx file text from google drive? How to implement with use of libary any suggection
I'm using image_picker & ImageCropper packages. I want to save a user-given picture in firestore database. So, I use functions like this.
First, set File? _image;
Functions for cropping & picking
Future _pickImage(ImageSource source) async {
Navigator.of(context).pop();
try {
final image = await ImagePicker().pickImage(source: source);
if (image == null) return;
File? img = File(image.path);
img = await _cropImage(imageFile: img);
setState(() {
_image = img;
});
} on PlatformException catch (e) {
print(e);
Navigator.of(context).pop();
}
}
Future<File?> _cropImage({required File imageFile}) async {
CroppedFile? croppedImage =
await ImageCropper().cropImage(sourcePath: imageFile.path);
if (CroppedFile == null) return null;
return File(croppedImage!.path);
}
and use this to save data in firestore
Future<String> uploadImageToStorage(
File file,
) async {
file
Reference ref =
_storage.ref().child("profilePics").child(_auth.currentUser!.uid);
UploadTask uploadTask = ref.putData(file);
TaskSnapshot snap = await uploadTask;
String downloadUrl = await snap.ref.getDownloadURL();
return downloadUrl;
}
Above function not work for File type data, It support for Uint8List. So, What can I do for this?
Next problem is, I'm getting File type data with ImagePicker for profile picture. Is it not problem?
Try changing your _cropImage-Method to return XFile? like this:
Future<XFile?> _cropImage({required File imageFile}) async {
CroppedFile? croppedImage =
await ImageCropper().cropImage(sourcePath: imageFile.path);
if (CroppedFile == null) return null;
return XFile(croppedImage!.path);
}
You also have to change the paramter of uploadImageToStorage to XFile file. Then you can use file!.readAsBytes(); to get a Uint8List.
Future<String> uploadImageToStorage(
XFile file,
) async {
Reference ref =
_storage.ref().child("profilePics").child(_auth.currentUser!.uid);
final fileBytes = await file.readAsBytes();
UploadTask uploadTask = ref.putData(fileBytes);
TaskSnapshot snap = await uploadTask;
String downloadUrl = await snap.ref.getDownloadURL();
return downloadUrl;
}
I want to add the function which can upload multiple Photo image via ImagePicker
In this code, I can just upload single photo, not mutiple.
This app operating by flutter, dart and firebase server.
[Code]
void dispose() {
textEditingController.dispose();
super.dispose();
}
File _image;
Future _getImage() async {
var image = await ImagePicker.pickImage(
source: ImageSource.gallery,
maxWidth: 1000,
maxHeight: 1000,
);
setState(() {
_image = image;
});
}
Future _uploadFile(BuildContext context) async {
if (_image != null) {
final firebaseStorageRef = FirebaseStorage.instance
.ref()
.child('post')
.child('${DateTime.now().millisecondsSinceEpoch}.png');
final task = firebaseStorageRef.putFile(
_image,
StorageMetadata(contentType: 'image/png'),
);
final storageTaskSnapshot = await task.onComplete;
final downloadUrl = await storageTaskSnapshot.ref.getDownloadURL();
await Firestore.instance.collection('post').add(
{
'contents': textEditingController.text,
'displayName': widget.user.displayName,
'email': widget.user.email,
'photoUrl': downloadUrl,
'userPhotoUrl': widget.user.photoUrl,
});
}
final images = await _picker.pickMultiImage(
maxHeight: 1024,
maxWidth: 1024,
imageQuality: 50,
);
I created here 3 functions used to pick files from imagePicker and to upload them to firebase storage.
first, pick images from gallery:
final imageFiles = await pickImages();
second, upload the images:
final path = 'path/where/you/want/to/save/your/images';
final imageUrls = uploadImages(imagesFiles, path)
print(imageUrls);
you can now use the images urls to save to firestore
Future<List<File>> pickeImages() async {
ImagePicker picker = ImagePicker();
final images = await picker.pickMultiImage(
maxHeight: 1000, maxWidth: 1000, imageQuality: 90);
List<File> files = [];
if (images == null || images.isEmpty) return [];
for (var i = 0; i < images.length; i++) {
final file = File(images[i].path);
files.add(file);
}
return files;
}
Future<String?> _uploadImageFile(File file, String path) async {
try {
final storage = FirebaseStorage.instance;
TaskSnapshot? taskSnapshot;
final storageRef = storage.ref().child(path);
final uploadTask = storageRef.putFile(file);
taskSnapshot = await uploadTask.whenComplete(() {});
final imageUrl = await taskSnapshot.ref.getDownloadURL();
return imageUrl;
} catch (e) {
throw Exception(e.toString());
}
}
Future<List<String>> uploadImages(
List<File> files,
String path,
) async {
final urls = <String>[];
try {
if (files.isNotEmpty) {
for (var i = 0; i < files.length; i++) {
final file = files[i];
final imagePath = '$path/${Random().nextInt(10000)}.jpg';
final url = await _uploadImageFile(file, imagePath);
urls.add(url!);
}
}
return urls;
} on FirebaseException {
rethrow;
}
}
Instead of using ImagePicker.pickImage, use ImagePicker.pickMultiImage. That gives you a List instead of an XFile. Then you can just upload all images in the list. For instance, add an image parameter to your _uploadFile Function so that its function signature is
Future _uploadFile(BuildContext context, XFile image)
and just upload all images like
for (final image of images) {
_uploadFile(context, image)
}
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 creating a disk cache and I faced problem while running flutter tests cause by json.decode() but I found that the problem is that the same file is being read twice at the same time.
Here is the code for the disk cache class:
import 'dart:convert';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:the_chef/repositories/cache/base_cache.dart';
class DiskCache<V> extends BaseCache<List<String>, V> {
String directoryPath;
DiskCache({
BaseCache<List<String>, V> other,
}) {
next = other;
}
Future<V> _get(List<String> path) async {
print("get $path");
var val;
var file;
file = await _exists(path);
if (file != null) {
print("start");
var str = await file.readAsString();
val = json.decode(str);
print("end get $path");
return val;
}
val ??= next?.get(path);
if (val != null) {
await _createFile(file);
var bytes = json.encode(val);
await file.writeAsString(bytes);
}
if(val == null) {
print("notfound");
}
return val;
}
Future<V> get(List<String> path) async {
var x = await _get(path);
return x;
}
#override
Future<void> set(List<String> path, V value) async {
print("set $path");
final file = await _createFileFromPath(path);
var bytes = json.encode(value);
await file.writeAsString(bytes);
next?.set(path, value);
print("end set $path");
}
#override
Future<void> evict(List<String> path) async {
print("evict $path");
final file = await _localFile(path);
if (await file.exists()) {
await file.delete();
} else {
await file.delete(recursive: true);
}
await next?.evict(path);
}
Future<File> _exists(List<String> path) async {
var file = await _localFile(path);
return (await file.exists()) ? file : null;
}
Future<File> _localFile(List<String> filePath) async {
final path = await _localPath();
return File('$path/${filePath.join('/')}');
}
Future<String> _localPath() async {
if (directoryPath != null) {
return directoryPath;
}
directoryPath = (await getApplicationDocumentsDirectory()).path;
return directoryPath;
}
Future<File> _createFileFromPath(List<String> path) async {
var file = await _localFile(path);
await _createFile(file);
return file;
}
Future<void> _createFile(File file) async {
file.createSync(recursive: true);
}
}
It would be very great if you have any suggestion of how to improve the cache or have any other advices.
Thanks in advance.