How to get the original path of an image chosen with image picker plugin in Flutter instead of copying to cache? - flutter

I'm making an Android app, and when using the image picker plugin;
final pickedFile = await ImagePicker().getImage(source: ImageSource.gallery);
File image = File(pickedFile.path);
the 'image' is a copy of the original image in the app's cache, however, I would like to directly use the original image's path to save it in my app because I don't want the apps cache size to grow. I saw that the deprecated method "pickImage" accomplished this (not copying to cache), but the new "getImage" seems to copy automatically and 'image's path is the path of the cached image.
How can I accomplish getting just the original path of the selected image without it being cached? (I'm assuming that using the original file's path would still work to display it in the app with FileImage(File(originalPath)), this is correct assumption?)

On iOS it was never possible to retrieve the original path and on Android it was only possible until SDK 30.
From FAQ of file_picker plugin,
Original paths were possible until file_picker 2.0.0 on Android, however, in iOS they were never possible at all since iOS wants you to make a cached copy and work on it. But, 2.0.0 introduced scoped storage support (Android 10) and with and per Android doc recommendations, files should be accessed in two ways:
Pick files for CRUD operations (read, delete, edit) through files URI and use it directly — this is what you actually want but unfortunately isn’t supported by Flutter as it needs an absolute path to open a File descriptor;
Cache the file temporarily for upload or similar, or just copy into your app’s persistent storage so you can later access it — this is what’s being done currently and even though you may have an additional step moving/copying the file after first picking, makes it safer and reliable to access any allowed file on any Android device.

I have an example for the file_picker package:
var filePath = '';
var fileExtension = '';
var fileName = '';
void buttonOnTap() async {
try {
filePath = await FilePicker.getFilePath(type: FileType.IMAGE);
if (filePath != null) {
fileName = filePath.split('/').last;
fileExtension = fileName.split('.').last;
} else {
filePath = '';
fileName = '';
fileExtension = '';
}
} catch (e) {}
if (filePath != '') {
Image.file(File(filePath), fit: BoxFit.cover);
}
}

Related

Flutter, ImagePicker giving different paths every time for the same image

In my app, I am picking a photo from gallery and save it's path with ImagePicker. Then, I am showing it with the path I saved. The problem is, ImagePicker is giving me a different path every time even if I choose the same picture again so I can not open the image with the path I saved, it's giving the error no such file. How I am getting the path is:
onPressed: () async {
final XFile? image =
await imagePicker.pickImage(source: ImageSource.gallery);
if (image != null) {
setState(() {
imagePath = image.path;
});
}
},
It gives me a path like this: "/private/var/mobile/Containers/Data/Application/..." so on. How can I get the actual path and open it?
ImagePicker will create a copy of the image to your app's cache directory, thus you need to move it into a more stable location.
It also has no knowledge of what was picked before, thus it will create a new image every time you pick it. If you need to have a stable file path based on the image, perhaps give a try to file_picker.

How to convert file back to Asset

I am using the multiple file picker package on pub.dev, the link is below https://pub.dev/packages/multi_image_picker in conjunction with the image cropper package by Yalantis
https://pub.dev/packages/image_cropper
to let my user pick multiple images and then crop them at will.
I am using this code to convert my asset into a file and feed it into the cropper. And it works.
final temp = await Directory.systemTemp.createTemp();
final data = await finalList[index].getByteData();
File failo = await File('${temp.path}/img').writeAsBytes(
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
print("The path is ${temp.path}");
File croppedFailo = await ImageCropper.cropImage(
sourcePath: failo.path,
androidUiSettings: AndroidUiSettings(toolbarTitle: "My App"),
);
The tricky bit is to convert it back to an asset so that i can replace the old uncropped asset with this new cropped one..I read through the Asset documentation of the package and I tried this but it made my app crash
Asset croppedPic = new Asset(
croppedFailo.path,
DateTime.now().millisecondsSinceEpoch.toString(),
300,
300,
);
finalList.replaceRange(index, index + 1, [croppedPic]);
EDIT: When i say "asset", i am not referring to images i manually added to the assets/images folder in the app. The multi image picker plugin has a file- type called asset in which it returns images. That is the type to which i want to convert my file back into.
Never mind. I figured it's too unnecessarily complicated to do that. So, i instead just reformatted my entire code to handle images as files instead of assets. And, it actually made my life a lot simpler coz files give you more versatility and less problems than assets.

Where can I store the images for my android app?

I am building an app in flutter and I want to store many images. So will anyone suggest me where I can store the images which is easy to use in my app. I mean should I store it locally or in cloud? If yes which cloud or backend should I use, whichone is good and fully optimized for my flutter app (like mongo, django, firebase etc. ). Will anyone suggest me the best?
Anyone kind of help is appreaciated as I have no prior knowledge about the production part....
Storing Images on a server can be very expensive, since the file sizes are very large compared to the usual data. So if you do not NEED to store them on a server, don't.
Storing images locally is pretty simple. You will want to use the path_provider package https://pub.dev/packages/path_provider . I ll post a function I am using in my current project that does this. You ll see, its pretty simple.
Note: In my Code I pull the file from my server. Obviously leave that part out if you are getting your images from a different source.
Future<File> createFileOfPdfUrl(String fileLocation, String name) async {
final url = Helper.baseUrl + "Files/Newsletter/" + fileLocation;
final filename = url.substring(url.lastIndexOf("/") + 1);
var request = await HttpClient().getUrl(Uri.parse(url));
var response = await request.close();
var bytes = await consolidateHttpClientResponseBytes(response);
String dir = (await pathProvider.getApplicationDocumentsDirectory()).path;
File file = new File('$dir/$filename');
await file.writeAsBytes(bytes);
return file;
}

Loading video files from device as `ByteData` flutter

I'm using the flutter camera package to record videos and save videos to a temporary directory after which I use flutter's ffmpeg package to do some transformation. However, to achieved this, I first had to make a copy of the recorded video to create the output file path.
The challenge comes in when I'm trying to load the asset from the device. The block of code below does the copying and renaming of the file.
static Future<File> copyFileAssets(String assetName, String localName) async {
ByteData assetByteData = await rootBundle.load(assetName);
final List<int> byteList = assetByteData.buffer
.asUint8List(assetByteData.offsetInBytes, assetByteData.lengthInBytes);
final String fullTemporaryPath =
join((await tempDirectory).path, localName);
return new File(fullTemporaryPath)
.writeAsBytes(byteList, mode: FileMode.writeOnly, flush: true);
}
The issue lies with this line ByteData assetByteData = await rootBundle.load(assetName);
I get this error message Unable to load asset: /storage/emulated/0/Android/data/com.timz/files/timz/1585820950555.mp4, but the weird thing is, this only happens when I run the build for the first. Everything else works fine on subsequent hot restarts.
I later got this fix by myself rootBundle is meant for loading only assets you've declared their paths on your pubspec.yaml but somehow, it miraculously loads the saved file when hot restart was applied.
Reading the file as bytes gave what I wanted as load it with root bundle. Here's the code below.
Uint8List assetByteData = await File(assetName).readAsBytes();

Problems in descompression file - Out of memory

I have a sales app develpmented in Flex Builder. For use photos by off-line way, i upload a compressed file with all photos to the site and when need i sincronize with my smartphone. In that process is made a download to the dispositive and exist a responsable plugin to descompress the archive and disponibilize it in apropriate folder to later use.
That compressed file has 500MB size - 6700 photos approximately - and in Flex i have no type of problem to do that.
I'm rewriting the app in Flutter, using a archive package, dont getting the same results. In the descompress process i have problem with Out of memory.
Somebody already faced for something like that ?
Is there an best way to do this ?
I already tried other two alternatives:
- To use the Image.network, but, one of requires is work off-line.
- To save all the photos in assets folder, but i think that is not the best alternative, because the app will get bigger
Thank you in advance for.
Follow the error message and the code
code:
unarchiveAndSave()async{
var zippedFile = await initDir();
var bytes = zippedFile.readAsBytesSync();
var archive = ZipDecoder().decodeBytes(bytes);
for (var file in archive) {
var fileName = '$_dir/${file.name}';
if (file.isFile) {
var outFile = File(fileName);
print('File:: ${outFile.path}');
outFile = await outFile.create();
await outFile.writeAsBytes(file.content);
}
}
print('terminei de descompactar os arquivos');
}