Saving images and videos for offline access - flutter

I am developing an app that fetches a custom object from my REST API. The object's class is called MyItem and it looks like this:
class MyItem {
String title;
String profilePicURL;
String videoURL;
}
As you can see, the class contains two URLs, that points to a png and mp4 files.
I would like to implement a feature, which allows the user to download the object, in order to access its content offline. I have no problem saving the title property, but how can I save the two URLs (because I don't want the URL itself to be saved, I would like to save the file it points to).
Any idea what is the best way doing that in Flutter and Dart?
Thank you!

import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';
var directory = await getApplicationDocumentsDirectory();
Dio dio = Dio();
//Below function will download the file you want from url and save it locally
void Download(String title, String downloadurl) async{
try{
await dio.download(downloadurl,"${directory.path}/$title.extensionoffile",
onReceiveProgress: (rec,total){
print("Rec: $rec, Total:$total");
setState(() {
//just to save completion in percentage
String progressString = ((rec/total)*100).toStringAsFixed(0)+"%";
}
);
});
}
catch(e){
//Catch your error here
}
}
Now again wherever you want just use
var directory = await getApplicationDocumentsDirectory();
String filepath = "{directory.path}/filename.fileextension";
Now you can use this Image.file('filepath'); //to display those image
also you can use
video player plugin
where again VideoPlayerController.file('filepath') //to show video but read documention properly
These are just a whole steps or a broader view, you need to use them as a map and build your code.That is have a proper file name and extension saved or correctly fetched or mapped

Related

flutter image picker reduce file size with provider and flutter_image_compress

I am using image picker to pick image from device(App) and after that stored that file in provider class like that.
File? _img;
get img=> _img;
void putbannerimg(File img) {
_img = img;
notifyListeners();
}
I found out that image picker does not compress png images, I tried compressing it with flutter_image_compress
compressFile() async {
final formservice = Provider.of<PostForm>(context, listen: false);
File file = formservice.bannerfile;
final result = await FlutterImageCompress.compressWithFile(
file.absolute.path,
quality: 54,
);
formservice.putbannerimg(File.fromRawPath(result!));
}
I tried this way And other multiple ways but getting different different errors I want to upload this file in firebase storage like this
var task = storageicon.putFile(formservice.iconfile);
please tell me where I am going wrong, without compress file all things are working fine
Edit: I found out that path should be a string how can I parse local code file in that
If you are using the "flutter_image_compress" package
You may have to use the compress function for files stored on the phone like this:
Future<File> testCompressAndGetFile(File file, String targetPath) async {
var result = await FlutterImageCompress.compressAndGetFile(
file.absolute.path, targetPath,
quality: 88,
rotate: 180,
);
print(file.lengthSync());
print(result.lengthSync());
return result;
}
"compressAndGetFile()" returns a file while "compressWithFile()" returns a Uint8List.
If i understand your last question right, you want to use an image built into your application by default.
For this, you have to open your "pubsepc.yaml", go to the "flutter:" mark and add "assets:" like so:
flutter:
assets:
- path
"path", in my example, describes a top level folder containing assets like pictures.
You can freely describe its name.

Flutter Web download file from url instead of opening it

Is there any way to get files like .pdf downloaded directly on user's device instead of opening this pdf in the browser?
This code works for downloading non browser supported files but it opens pdf, mp3, etc. in the browser.
final anchor = AnchorElement(
href: pickedFile)
..setAttribute("download", fileName)
..click();
If someone is still searching for solution.Here is what I have done.
Anchor tag will directly download file if it has download attribute.
Note: Download attribute is only supported for same-origin request
So instead of assigning external URL link to anchor element. Create Blob object from PDF data and create Object URL from that.
var url = Url.createObjectUrlFromBlob(Blob([data]));
AnchorElement(href: url)
..setAttribute('download', '<downloaded_file_name.pdf>')
..click();
I am using Firebase to store file so here is the complete code.
FirebaseStorage.instance.ref(resumeFileName).getData().then(
(data) {
var url = Url.createObjectUrlFromBlob(Blob([data]));
AnchorElement(href: url)
..setAttribute('download', '<downloaded_file_name.pdf>')
..click();
}
);
by following the steps below, you can download the file automatically by the browser and save it in the download directory.
In this method, http and universal_html packages are used.
The important thing is to manage Multiplatform-Mode and using this code, is better you create 3 separate dart files.
switch_native_web.dart
web.dart
native.dart
/// switch_native_web.dart
import 'native.dart' if (dart.library.html) 'web.dart' as switch_value;
class SwitchNativeWeb {
static void downloadFile({required String url,
required String fileName ,required String dataType}){
switch_value.downloadFile(dataType: dataType,fileName: fileName,url: url);}
}
...
/// web.dart
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:universal_html/html.dart' as universal_html;
Future<void> downloadFile(
{required String url,
required String fileName,
required String dataType}) async {
try {
// first we make a request to the url like you did
// in the android and ios version
final http.Response r = await http.get(
Uri.parse(url),
);
// we get the bytes from the body
final data = r.bodyBytes;
// and encode them to base64
final base64data = base64Encode(data);
// then we create and AnchorElement with the html package
final a =
universal_html.AnchorElement(href: '$dataType;base64,$base64data');
// set the name of the file we want the image to get
// downloaded to
a.download = fileName;
// and we click the AnchorElement which downloads the image
a.click();
// finally we remove the AnchorElement
a.remove();
} catch (e) {
print(e);
}
}
...
/// native.dart
Future<void> downloadFile({required String url, required String fileName,
required String dataType}) async {}
And using the following sample code for calling the downloadFile method wherever you need:
...
GestureDetector(
onTap: () => SwitchNativeWeb.downloadFile(
url: "https://... your url ..../download.jpg",
fileName: "download.jpg",
dataType: "data:image/jpeg"),
child: Text('download')
)
...
I only wrote the code related to web download (according to the question), you can write the code related to ios and android download in the native .dart file.
Use Dio Library.
dependencies:
dio: ^3.0.10
to download file
response = await dio.download("https://www.google.com/", "./xx.html");
this video will help you.

Store image uploaded by user into Flutter Web as an actual .jpg file

I am using the flutter_web_image_picker package to allow the user to select -and then upload to Firebase- an image.
However, the package returns an image widget, which I can display, but I cannot upload to Firebase. Therefore, I am trying to read the package's code and update it to fit my needs.
In general, I think the packages main functionalities are:
It gets the file
//...
final reader = html.FileReader();
reader.readAsDataUrl(input.files[0]);
await reader.onLoad.first;
final encoded = reader.result as String;
Then it 'strippes' it
final stripped = encoded.replaceFirst(RegExp(r'data:image/[^;]+;base64,'), '');
final imageName = input.files?.first?.name;
//...
To finally return it as a Widget:
final imageName = imageName;
final imageData = base64.decode(stripped);
return Image.memory(imageData, semanticLabel: imageName);
As I said, it works perfectly, however, I need to adapt it to my needs:
I would like to get the image as a .jpg file so that I can upload it to Firebase.
Is any of the variables above the actual .jpg file? Is there any transformation that I should perform to get a .jpg file?
Thanks!
I based my answer on this post.
Basically, on the flutter_web_image_picker package, before the code I posted, there were a few lines that get an actual html file:
final html.FileUploadInputElement input = html.FileUploadInputElement();
input..accept = 'image/*';
input.click();
await input.onChange.first;
if (input.files.isEmpty) return null;
Then using firebase's pacakge, I uploaded the image as follow:
import 'package:firebase/firebase.dart' as fb;
fb.StorageReference storageRef = fb.storage().ref('myLocation/filename.jpg');
fb.UploadTaskSnapshot uploadTaskSnapshot = await storageRef.put(input.files[0]).future;
Uri imageUri = await uploadTaskSnapshot.ref.getDownloadURL();
return imageUri;

File modified data is always current time

I am using the following code snippet to attempt to retrieve the modified time of a file:
import 'dart:io';
import 'package:image_picker/image_picker.dart';
final picker = ImagePicker();
final pickedFile = await picker.getVideo(source: ImageSource.gallery);
final file = File(pickedFile.path);
print("file modified time: ${file.lastModifiedSync().toIso8601String()}");
Whenever I run the the above snippet, regardless of the file, it prints the current dateTime as opposed to the file's modified dataTime
The way the image_picker work is it creates a temporary copy of the file which you are about to upload in your app. With this implementation, the "current date" you are mentioning is the logically the file's "last modified date" (or creation date). So for now, you may not be able to retrieve it using this plugin.
However, with Flutter's Platform Channels, you should be able to retrieve the file's attributes, eg. for Android, using BasicFileAttributes in native code.
For example in Android:
File file = ...;
BasicFileAttributes attr = Files.readAttributes(file.toPath(), BasicFileAttributes.class);
long lastModifiedAt = attr.lastModifiedTime();
Then using platform channels, you can pass the data like this to Flutter:
result.success(lastModifiedAt)
References
BasicFileAttributes
https://stackoverflow.com/a/48431255/10942908
Flutter's Platform Channels
I don't believe this information is available, unfortunately (at least on Android, not sure about iOS)
Tested using the file_picker package, hope that can help up with the image_picker.
You can use the cross_file package.
FilePickerResult? result = await FilePicker.platform.pickFiles();
final resultFile = result.files.first;
final resultFilePath = resultFile.path;
if (resultFilePath == null) {
throw EntityPathException();
}
/// Class from cross_file package
final xfile = XFile(resultFilePath);
final lastModified = await xfile.lastModified();
You can use multi_image_picker package instead. The creation time of the selected image(s) can be accessed through the MetaData class as indicated below:
List<Asset> images = await MultiImagePicker.pickImages(maxImages: 10, enableCamera: true);
Metadata metadata = await images[0].metadata;
DateTime takenOn = metadata.exif.dateTimeOriginal;

Flutter how to Convert filePath from content://media/external/images/media/5275 to /storage/emulated/0/DCIM/Camera/IMG_00124.jpg

I have URI LIKE below
content://media/external/images/media/5275
but I want convert it to Like format below:
/storage/emulated/0/DCIM/Camera/IMG_00124.jpg
Anyone who can help me!
Sreng Bona
Thanks!
var path = await FlutterAbsolutePath.getAbsolutePath("content://media/external/images/media/5275");
Add this flutter_absolute_path: ^1.0.6 to your file: pubspec.yaml
It will be working as Well.
Bona SR.
I had to search a lot, but I found a very useful solution to save the image in the cell phone's photo gallery and get the absolute path to use it the way you want.
For this example I used a result obtained from saving an image in the photo gallery, however it could also work to read other files, obviously making the changes that you see necessary, I hope it will help you
uri_to_file
image_gallery_saver
import 'dart:io';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:uri_to_file/uri_to_file.dart';
Future<File> saveImage(File image, String identifier) async {
try {
var result = await
ImageGallerySaver.saveImage(image.readAsBytesSync(),
quality: 60, name: identifier +
"-${DateTime.now().toIso8601String()}");
print(result);
File file = await toFile(Uri.parse(result['filePath']));
print(file);
return file;
} catch (e) {
print(e);
return new File('assets/img/default-img.jpg');
}
}
// example
saveImage(File("path/image.jpg"),"img-test");