How to fetch filename from url [Flutter][Dio] - flutter

This is My code snippet instead of mypdf.pdf i want to get filename from the url like in android app development,since I'm new in flutter i have no idea can anyone help me
Future<void> downloadPDF() async {
Dio dio = Dio();
try {
var dir = await getApplicationDocumentsDirectory();
await dio.download(pdfurl, "${dir.path}/mypdf.pdf",
onProgress: (rec, total) {
setState(() {
downloading = true;
progressString = ((rec / total) * 100).toStringAsFixed(0) + "%";
});
});
} catch (e) {
print(e);
}
setState(() {
downloading = false;
progressString = "Completed";
});
print("Download completed");
}

did you try it ?
File file = new File("/dir1/dir2/file.ext");
String basename = basename(file.path);
# file.ext
for more details https://flutter.dev/docs/cookbook/persistence/reading-writing-files

You can use the built-in substring and lastIndexOf methods:
final url = "http://africau.edu/images/default/sample.pdf";
final filename = url.substring(url.lastIndexOf("/") + 1);

Related

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

Flutter download file in phone storage

I am not able to download file in the phone storage.. My code is..
Future<void> downloadFile() async {
Dio dio = Dio();
bool checkPermission1 =
await SimplePermissions.checkPermission(permission1);
print('checkPermission1');
print(checkPermission1);
if (checkPermission1 == false) {
await SimplePermissions.requestPermission(permission1);
checkPermission1 = await SimplePermissions.checkPermission(permission1);
}
if (checkPermission1 == true) {
String dirloc = "";
if (Platform.isAndroid) {
dirloc = "/sdcard/downloads/";
} else {
dirloc = (await getApplicationDocumentsDirectory()).path;
}
try {
FileUtils.mkdir([dirloc]);
await dio.download(url, dirloc + id + ".mp4",
onReceiveProgress: (receivedBytes, totalBytes) {
setState(() {
downloadingFlag = true;
progress =
((receivedBytes / totalBytes) * 100).toStringAsFixed(0) + "%";
});
});
} catch (e) {
print(e);
}
setState(() {
downloadingFlag = false;
downloadsFlag = false;
progress = "Download Completed.";
path = dirloc + id + ".mp4";
});
} else {
setState(() {
progress = "Permission Denied!";
});
}
}
I/flutter (23004): FileSystemException: Creation failed, path = '/sdcard/downloads' (OS Error: Permission denied, errno = 13)

Cannot save a file to the documents directory IOS Flutter

I tried to test the file download and saving to the documents directory. The code works on Android, but fails on IOS. Here is the code:
var dir = await getApplicationDocumentsDirectory();
var documentName = "";
documentName = "testname.pdf";
var storePath = "${dir.path}/$documentName";
var errorOccurred = false;
try {
await dio.download(url, storePath, onReceiveProgress: (rec, total) {
print("Rec: $rec , Total: $total");
_setState(() {
downloading = true;
progressString = ((rec / total) * 100).toStringAsFixed(0) + "%";
});
});
} catch (e) {
print(e);
}
The error is the following:
Exception: PlatformException(file_not_found, File not found: '/../Devices/3D122270-E919-455D-AF3F-F048EC32CBB7/data/Containers/Data/Application/1262A294-59DC-47A5-B5A6-24FBAD9D53CA/Library/Caches/testname.pdf', null, null)
I am testing on simulator

readAsBytesSync is incomplete

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

Flutter async/await is not working between 2 Firebase functions

I'm trying to call a cloud firestore function that has to persist an object only when another function returns the url of the file in Firebase Storage but the async await is not working and the second function is called anyway whereas the first function is not yet completed!!!
await schoolProfileProvider.uploadSchoolProfileAvatar(data).then( (data) {
schoolProfileProvider.addSchoolProfile(data);
});
print('PROFILE ADDED');
Future<SchoolProfileData> uploadSchoolProfileAvatar(SchoolProfileData data) async {
List<File> avatars = [];
data.childrenDetails.forEach((child) {
avatars.add(File(child.childImage));
});
try {
await _api.uploadFilesToStorage(avatars, 'image', 'png').then((urls) {
for (var i = 0; i < urls.length; i++) {
data.childrenDetails[i].childImage = urls[i];
print('ADD ' + data.childrenDetails[i].childImage);
}
});
} on Exception catch (e) {
print(e.toString());
}
return data;
}
T cast<T>(x) => x is T ? x : null;
Future<List<String>> uploadFilesToStorage(List<File> files, String type, String extension) async {
final urls = <Future<String>>[];
files.forEach((file) async {
StorageReference storageRef = storage.ref().child(file.path);
final StorageTaskSnapshot downloadUrl =
(await storageRef
.putFile(file, StorageMetadata(contentType: type + '/' + extension))
.onComplete);
await downloadUrl.ref.getDownloadURL().then((url) {
urls.add(cast<Future<String>>(url));
print('URL for file ${file.path} = ${url.toString()}');
});
});
print ('urls returned');
return Future.wait(urls);
}
Future addSchoolProfile(SchoolProfileData data) async{
var result;
try {
result = await _api.addDocument(data.toJson());
} on Exception catch(e) {
print (e.toString());
}
return result;
}
I've managed to make the things work and execute addSchoolProfile only after uploadFilesToStorage is completed by reducing the nested functions and making the await downloadUrl.ref.getDownloadURL() as the last instruction returned in the callee function.
Please find the code for who is interested in :
The caller :
schoolProfileProvider.addSchoolProfileAndUploadAvatar(data);
Future addSchoolProfileAndUploadAvatar(SchoolProfileData data) async {
List<File> avatars = [];
data.childrenDetails.forEach((child) {
avatars.add(File(child.childImage));
});
try {
for (int i=0;i<avatars.length;i++){
await _api.uploadFileToStorageAndGetUrl(avatars[i], 'image', 'png').then((url) {
print('URL for file ${avatars[i].path} = ${url.toString()}');
data.childrenDetails[i].childImage = url;
print('ADD ' + data.childrenDetails[i].childImage);
});
}
_api.addDocument(data.toJson()) ; // Add document in Google Firebase after setting the avatar url
} on Exception catch (e) {
print(e.toString());
}
}
The callee :
Future <String> uploadFileToStorageAndGetUrl(File file,String type, String extension) async{
StorageReference storageRef = storage.ref().child(file.path);
final StorageTaskSnapshot downloadUrl =
(await storageRef
.putFile(file, StorageMetadata(contentType: type + '/' + extension))
.onComplete);
return await downloadUrl.ref.getDownloadURL(); // return the url of the file in Google Storage
}