readAsBytesSync is incomplete - flutter

Since I can't convert convert a file directly from url (e.g File(url)).
I am downloading the file and then use the temp file path.
I tried different files : images, pdfs and it's still incomplete.
Am I doing something wrong here?
Future<String> downloadFile() async {
print(imgUrl);
Dio dio = Dio();
try {
var dir = await getApplicationDocumentsDirectory();
await dio.download(imgUrl, "${dir.path}/${widget.name}.pdf",
onReceiveProgress: (rec, total) {});
path = "${dir.path}/${widget.name}.pdf";
setState(() {
downloading = false;
progressString = "Completed";
});
if (path != null) {
List<int> imageBytes = File(path).readAsBytesSync();
print("NEW BYTE : $imageBytes");
}
} catch (e) {
print(e);
}
return path;
}

Checkout this solution:-
https://gist.github.com/Nitingadhiya/3e029e2475eeffac311ecd76f273941f
Uint8List? _documentBytes;
getPdfBytes() async {
_documentBytes = await http.readBytes(Uri.parse('https://cdn.syncfusion.com/content/PDFViewer/flutter-succinctly.pdf'));
return _documentBytes;
}
Future<void> readPDf() async {
//Load the existing PDF document.
Uint8List documentInBytes = await getPdfBytes();
final PdfDocument document = PdfDocument(inputBytes: documentInBytes);
//Get the existing PDF page.
final PdfPage page = document.pages[0];
//Draw text in the PDF page.
page.graphics.drawString('Hello World!', PdfStandardFont(PdfFontFamily.helvetica, 12), brush: PdfSolidBrush(PdfColor(0, 0, 0)), bounds: const Rect.fromLTWH(0, 0, 150, 20));
//Save the document.
final List<int> bytes = await document.save(); //document.saveSync();
await saveAndLaunchFile(bytes, 'Invoice.pdf');
//Dispose the document.
document.dispose();
}
Future<void> saveAndLaunchFile(List<int> bytes, String fileName) async {
//Get the storage folder location using path_provider package.
String? path;
if (Platform.isAndroid || Platform.isIOS || Platform.isLinux || Platform.isWindows) {
final Directory directory = await path_provider.getApplicationSupportDirectory();
path = directory.path;
} else {
path = await PathProviderPlatform.instance.getApplicationSupportPath();
}
final File file = File(Platform.isWindows ? '$path\\$fileName' : '$path/$fileName');
await file.writeAsBytes(bytes, flush: true);
if (Platform.isAndroid || Platform.isIOS) {
//Launch the file (used open_file package)
// await open_file.OpenFile.open('$path/$fileName');
} else if (Platform.isWindows) {
await Process.run('start', <String>['$path\\$fileName'], runInShell: true);
} else if (Platform.isMacOS) {
await Process.run('open', <String>['$path/$fileName'], runInShell: true);
} else if (Platform.isLinux) {
await Process.run('xdg-open', <String>['$path/$fileName'], runInShell: true);
}
}

Related

How to Read a docx file text from google drive?

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

ImageCropper use with Uint8List file -flutter

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

How can I upload mutiple-photo in flutter app via ImgePicker

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

Cannot get the download link after uploading files to firebase storage Flutter

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

Prevent Concurrent Access to File in Dart

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.