-
Notifications
You must be signed in to change notification settings - Fork 720
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The problem with big files #561
Comments
@sbilketay there isn't much to do here, unfortunately. Files are copy cached in chunks which is great to prevent memory issues, however, 4GB is too much for some devices to handle as you need always 4GB available + some space left. If you have devices with 10/15 GB of left storage, it shouldn't be an issue (other than just taking the time to download it). |
I'm not interested in downloading files. I want to get the size of a video that is already in the gallery. Is there a way to do this without waiting? |
@sbilketay right now that isn’t possible. But it’s possible to add as a feature. |
I'm facing this same issue, caching the file then loading for larger files proves to be an issue when reading the files on devices, especially lower performance android devices. Is there a way to append an option to get a direct path? |
☝️ |
@tmthecoder @sbilketay that's not possible since SDK 30. It is only possible on Android native (through URIs which allows you to manipulate files directly without relying on its original path, however Flutter doesn't support native Android URIs and needs absolute paths for files). You can read more about it here in the first question. |
Oh, my bad, that's right I forgot about the Scoped Storage stuff on Android. I'm still wondering if there's a way to speed up the process as caching is one of the longest processes in my file work process. |
I just want to write that I critically need a solution to this issue as well. My app is primarily a video player and some files I want to play are 4GB huge and crashes at file selection. I can't seem to implement something like resuming video playback because that would require the video to be cached in the app's scoped storage. My temporary solution is to offer separate versions for users below Android 11 and those on or above it, which is a bit of extra work. With legacy storage, videos play instantly. There isn't copying involved. No videos that have to be moved to cache and clearing after use. No videos that are too huge to play. It just worked. Scoped storage has been incredibly high maintainance. Secure at the cost of mind numbingly slow limitations. I understand this must be hard to deal with but I would really appreciate any word on a solution to this problem. |
@lrorpilla unfortunately, the only possible solution for this, is if Dart allows us to create Other way I can think is if we could stream the data directly from each platform, which is doable with some effort I believe but might not fit your use case as well, since you need a |
Following this as we also ran into this issue |
Maybe we can add some sort of 'withDirect' parameter when opening the file which will stream the data directly from the platform (only applicable to android?). I'd be open to helping write this if needed |
If the APP has MANAGE_EXTERNAL_STORAGE permission, is it possible to use the original path directly? |
I get memory leakage issue when select a pdf file with size 40mb |
What would you return to Dart in this case? |
I was thinking of a callback-style function that we can listen on in dart and add to a Stream with the bytes. So my thoughts are: Start a |
@tmthecoder well, that’s sort of the same that happens when you enable |
@miguelpruivo The |
Is there no way of disabling this caching and moving the responsibility to package users? Picking large files is unbearably slow. This also makes me wonder, how apps such as instagram are able to flawlessly handle huge local files (video) without any noticeable delay for caching. |
I have this problem too, I am trying to pick files of an external USB device. The whole point of this is that I don't have enough memory on my device. This caching problem defeats the whole purpose of this! As a workaround, I am currently using Proposals: Also, you could implement a switch to not cache files and just return an error, if the file exceeds a specified file size. Maybe even dependent on the storage left on the device. This wouldn't really solve the main Problem, but at least, the Application still works if the User tries to cache a file that is too large. I really hope this can and will be fixed soon! |
Android guidelines don’t allow you to have absolute path access since SDK 30 for files. It’s probably working for you when you use the directory path to access the files, but using the native API to launch the picker and then handling the intent result with the files, don’t allow me to access the absolute paths. It was possible before, but then refactored due to this limitation. The recommended way to handle the original file is through its URI which is provided in the I’m not sure if what you’re asking is possible at all at this point, tbh. |
@miguelpruivo Is there any way to restrict the file size while selecting file? |
@msarkrish not that I'm aware of (at least, in all platforms). But you can always check the size after the user picks the file and then show an error to the user that the file is too big and discard it. |
Thanks @abhi16180, I'll try to look into your fork sometime. Just as an update because I still subscribe to this issue, I use filesystem_picker and supply root paths from external_path as an initial path and just list all the files in a directory and display them all in Flutter UI. Really my use case just requires the absolute file path to be able to make a file for a video player, so I just use a non-native file picker made with Flutter that lists everything in a directory and allows navigating and changing directories. Really being able to list every file in a directory allows me to have the absolute path I need. It's unfortunate I couldn't do this with the native picker plugins like this one, but to people who have a similar use case, you could consider what I did, it also allows you to have control over your UI. |
Yeah I will look into filesystem_picker package. |
Hey @lrorpilla, I've been trying to do something similar to what you've explained here but I haven't dug too deeply to solve my issues yet.
I'll have to take a look into filesystem_picker myself, as I am aiming to display a list of videos too but from external storage. When you use filesystem_picker to list all of your video files in a UI to select for playing, do you then experience caching when you select a file to play or are you playing using the direct path? |
@cnoons-cyq I've forked filesystem_picker for my purposes and it works great with no caching -- you get the absolute path you picked. I use it alongside external_paths to get roots to the internal storage and micro SD card if it exists on a device. |
Is #1258 similar to this? |
Android 10+ still allows to access real path with "MANAGE_EXTERNAL_STORAGE" permission. I'm not familiar with native Android development, but I would suggest the below approach,
|
I got your point but I don't intend to let the users access/manipulate the original files directly with this to prevent, somehow, unexpected implementations and bad behavior when the user accidentally edits an original file in any given app. The original approach of the official image_picker was to always cache/copy the files, so I follow the same path as per good practices. The user can always delete the original file later if he wants to. Also, having to support this would make it a requisite for all platforms or else in Android it could pick the original file and in iOS the users would pick a copy. The dev would have to handle this cases. Having a cache/copy behaves similar to mobile platforms. But I'm open to discuss alternatives. |
How about skipping expensive cache/copy and exposing content URI's on Android which then can be converted to Stream using this package: https://pub.dev/packages/uri_content ? UPDATE: On the Flutter side user can get: FilePickerResult? result = await FilePicker.platform.pickFiles(
allowMultiple: true,
allowCompression: false,
withReadStream: UniversalPlatform.isWeb
);
final uriContent = UriContent(); // https://pub.dev/packages/uri_content
for (final file in result.files) {
final uri = Uri.parse(file.identifier!);
final stream = uriContent.getContentStream(uri);
// Then you can pass the stream to and enjoy your app not crashing if big file is used, alternatively if you need to process stream all at once, then use: "content = await stream.expand((element) => element).toList();"
} The only drawback so far that I've experienced is that: |
…bliged me to change everything at once. Waiting to see how flutter/flutter#147037 and miguelpruivo/flutter_file_picker#561 do before posting 1.4.0
…bliged me to change everything at once. Waiting to see how flutter/flutter#147037 and miguelpruivo/flutter_file_picker#561 do before posting 1.4.0
flutter/flutter#147037 could solve this issue directly with Flutter's |
Are there any PRs for this issue or plans to fix it? |
It seems that there are two possible solutions on the radar. a) flutter/flutter#147037 is feasible once implemented by Flutter team as mentioned by @theskyblockman comment above. b) Solution mentioned here: #561 (comment) already works, except it doesn't work from a background isolate until Flutter team resolves this: flutter/flutter#119207 where they already make some progress. |
Since android 11 there's |
thats permission is too big what if all we need is just access to specific folder |
@miguelpruivo when are the cached files deleted ? i am worried that the device will run out of space, my use case handles multiple large (100-500mb) files. |
@iulian0512 You have to delete the files yourself, they are kept in your apps data directory. |
the file_picker i noticed that it makes those files when picking files, so my initial assumption was that it might handle its cache. |
If any of guys have a snippet that can cleanup these cache files that would be welcomed and likely help everyone here to deal with the cache size issue. In the meantime I believe this problem shall be tackled, so no cache files are needed at all. No cache files, no cleanup needed. |
i think for android it's best to use the document api https://developer.android.com/training/data-storage/shared/documents-files |
Sure, here's a snippet to delete all the files your user picked (not all of them). for (PlatformFile file in pickedFiles.files) {
File(file.path).deleteSync();
}
|
@iulian0512 @helomri Is there anyway to trigger cleanup e.g. periodically or when app starts or when file picker is requested? |
@tomekit the getContentStream() from https://pub.dev/packages/uri_content is feasible only for read operations, but if you need to write to a file say we need to save a file to a user defined location no bueno. |
You can simply use |
I am supposed to write an implementation in |
@iulian0512 Do you happen to know how this package: https://pub.dev/packages/file_picker |
Looking at flutter_file_picker/android/src/main/java/com/mr/flutter/plugin/filepicker/FilePickerPlugin.java Line 141 in 7726f3c
I can assure you no file is ever created in cache but the whole file is read into memory and sent through platform channels to the native side, which is obviously a gigantic problem (do NOT use it if you are saving user-generated files with unlimited size). |
as @helomri said |
I want to reach the size of the video files on the device. Low size videos are okay (eg 50mb). But if the file size is too big, it takes too long (eg 4gb). Sometimes it doesn't work. How can I directly access the path of the file I selected? When the file size is large, cache loading is a problem. I am having this problem on android.
The text was updated successfully, but these errors were encountered: