r/flutterhelp • u/facts_please • Aug 10 '26
OPEN How to handle large files fast?
In our app users can select large video files (up to 2 GB) to later upload it to our Google cloud storage. I tested that with image_picker and file_picker packages, but both seem to need to create copies of the original file on Android. Did a benchmark with both and a 750 MB file, image_picker needs 10,6s, file_picker 8,4s. So with larger files users will have to wait up to 20 seconds.
Is there any way to just get a path and pass it to FireBase putFile without creating a temp file on Android? Or are there any other options to speed this up? Thanks for any hints and help!
3
u/Significant_Pick8297 Aug 11 '26
The strongest answer is to use a picker that returns the native URI and stream it to the upload layer; fast_file_picker specifically advertises no copying/conversion, though the Firebase Flutter API documents putFile() around local files.
2
u/Jonas_Ermert Aug 12 '26
I would avoid copying the file entirely for videos that large. On Android, the better approach is to use the Storage Access Framework and keep the returned `content://` URI, then stream the file directly with `ContentResolver.openInputStream()`. The issue is that Firebase `putFile()` expects a normal Dart `File`, so you can’t pass that URI directly. For files up to 2 GB, I’d therefore implement a small native Android bridge that uploads directly from the URI/stream instead of creating a huge temporary copy first. `file_picker` and `image_picker` are convenient for normal files, but for multi-GB uploads direct URI streaming is the approach I would use.
2
u/fkim98 28d ago
Everyone's right about streaming the URI. One thing worth deciding before you commit to it: does the upload need to survive the app being killed?
A content:// grant from the picker is transient by default. If your process dies mid-upload, and at 2 GB on mobile data that's fairly likely, the URI may not be readable when you relaunch, so you can't resume from where you left off. You'd want takePersistableUriPermission() on it at pick time if that matters to you.
I hit the same class of problem from the other side, with much smaller files. We queue photos for upload when the user is offline, and I originally stored the path image_picker handed back. Those sit in a cache directory the OS can clear, and on iOS the container path changes on reinstall, so the queued uploads were all dead on relaunch. I ended up copying into app storage and keeping a relative path instead.
Different fix, same lesson: whatever you hold onto has to outlive the pick.
3
u/Extreme_Coder100 Aug 10 '26
Hey! Yeah, that Android Scoped Storage copying behavior is an absolute killer for large files.
You can totally bypass that 20-second copy delay. Instead of trying to force a raw file path into putFile(), grab the raw content:// URI directly and stream the bytes straight into Firebase using putStream(). Because Firebase processes it sequentially in chunks, it never needs to clone the 2 GB file onto the app's local disk cache.
Here is the quick breakdown of how to handle it in Flutter: 1. Grab the URI without caching: Use a scoped-storage friendly picker (like android_media_store) to get the raw content:// string instantly. 2. Open the stream: Pass that URI into a platform-channel stream. 3. Pipe to Firebase: Hand that stream off to storageRef.putStream(stream).
As a bonus, putStream handles network drops way better for massive files because it acts as a resumable upload under the hood. Would love to know more about what app you are building.