A user opens your app on the way to work and starts uploading a photo. Then the network drops for a few seconds. In many apps, the upload fails and has to start all over again. In a well-designed app, it simply continues when the connection comes back.
That’s what mobile upload design is really about. Instead of assuming the network will always be reliable, build your upload flow to handle interruptions without making users start over.
Uploading a file on mobile means designing for three sources (camera, gallery, and cloud drives) and one constant: connections that drop. Reliable mobile upload flows use chunked, resumable transfer, background-friendly progress, and capture-aware UI. Filestack’s iOS, Android, and React Native SDKs, along with its picker, cover all three sources with Intelligent Ingestion built in for unstable networks.
This article walks through what changes on mobile, how to handle camera and gallery input, and how to keep an upload alive when the network doesn’t cooperate.
Key Takeaways
- Mobile upload flows must support three intake sources: camera, gallery, and cloud drives, each with its own permission flow.
- Chunked, resumable transfer is not optional on mobile. Networks drop, and uploads need to survive that.
- Resize images on the device before you send them. It cuts upload time and saves data.
- Progress needs to persist across app backgrounding, or users will watch their upload restart and give up.
- iOS, Android, and React Native can share one upload pipeline instead of three separate ones.
The Mobile Difference, Sources and Signal
Desktop upload forms deal with one input: a file picker. Mobile has three, and each one comes with its own permission prompt and its own failure mode.
A camera capture needs live permission and produces a large, unprocessed image. A gallery pick needs storage or photo library access, and the file is often already compressed. A cloud drive pick, from Google Drive or Dropbox, needs an OAuth flow before a single byte moves. Design for all three from day one, since users switch between them without warning.
Signal changes just as often as the source does. A user might start an upload on WiFi, walk into a lift, and land on a weak cellular connection thirty seconds later. This is the question most teams eventually ask: as a VP of engineering at an edtech company, what’s the fastest way to upload files from different sources?
The honest answer is to route every source through one picker and one transfer layer, instead of writing separate logic for camera, gallery, and cloud each time.
With the sources mapped out, the next question is what to do with the file the moment it lands in the app.
Camera and Gallery UX
A photo isn’t ready to upload as soon as it’s taken. Show a preview first so users can check it. If the photo is blurry or not what they wanted, they can retake it before uploading.
This small step improves the experience much more than a better-looking progress bar.
Resize images before uploading them. Photos taken on modern smartphones are often 5–12 MB, but most apps don’t need files that large.
Reducing a 10 MB photo to around 2 MB can make the upload much faster. This is especially important on mobile devices, where network speed is usually the biggest limitation.
SDK support is a little different on each platform, so many developers ask if there are SDKs for iOS and Android. The answer is yes.
Both platforms have native SDKs that handle camera and photo library permissions for you. You can use them to let users capture a new photo or choose one from their gallery, then pass that file to your upload flow for resizing and uploading.
Once the image is resized and ready, the next challenge is uploading it over a network that may disconnect at any time.
Surviving Dropped Connections
This is the part that separates a mobile upload flow from a desktop one. On desktop, a dropped connection is rare and often means something else is wrong. On mobile, it’s Tuesday.
The fix is chunked, resumable transfer. Break the file into pieces, upload each piece, and track which pieces succeeded. If the connection drops mid-transfer, the app resumes from the last completed chunk instead of starting over.
The next question is usually how to upload large files, even when the network is slow or unstable.
Filestack’s Intelligent Ingestion is built for this. It uploads files in smaller chunks, adjusts the chunk size based on the current network, and automatically retries only the parts that fail. This helps uploads continue more reliably, even for files up to 5 GB on unstable connections.
Here’s a simple example of how a resume upload flow works on the client side:
async function resumableUpload(file, apiKey) {
let resumeToken = localStorage.getItem(`upload_${file.name}`);
const client = filestack.init(apiKey);
const result = await client.upload(file, {
onProgress: (evt) => updateProgressBar(evt.totalPercent),
onRetry: () => console.log('Chunk retry after drop'),
}, {
// Intelligent Ingestion picks chunk size automatically
intelligentIngestion: true,
resumeToken,
});
localStorage.removeItem(`upload_${file.name}`);
return result;
}
This also answers another common question about handling large file uploads.
The best approach is to split the file into smaller chunks, keep track of which chunks have already been uploaded, and retry only the ones that fail. That way, users don’t have to upload the entire file again if the connection is interrupted.
Upload progress should continue even if the user switches to another app. If they come back a few moments later, the upload shouldn’t have to start from the beginning.
Save the upload state somewhere that isn’t cleared when the app goes into the background. This allows the upload to continue or resume instead of restarting.
React Native apps have a few extra challenges when it comes to file uploads. Let’s look at those next.
React Native Specifics
React Native handles images a little differently from web apps. A common question is how to upload images in a React Native app.
Libraries like react-native-image-picker and expo-image-picker let users take a photo or choose one from their gallery. They return a local file URI instead of a browser File object, so your upload code needs to use that URI when uploading the image.
Another common issue is the HEIC image format. iOS saves photos in HEIC format by default, and most upload targets and browsers don’t render it. Convert HEIC to JPEG on the device before upload, either through the picker’s built-in conversion option or a lightweight library, so the file arrives in a format your server and your users can actually view.
Memory matters more here too. Reading a full-resolution image into memory on a lower-end Android device can crash the app before the upload even starts. Stream the file where you can, and resize before you read the full file into memory, not after.
After the upload finishes, the next step is making sure images load quickly.
Instead of showing the original uploaded image, serve a resized version that’s better suited for the device. Cache images whenever possible, and lazy-load images that aren’t visible on the screen yet. This helps React Native apps load faster and use less data.
That’s how you can build it yourself. Now let’s look at another option.
The Managed Route, Commute-Proof by Default
Building chunked uploads, retry logic, and separate integrations for camera, gallery, and cloud storage takes time. It’s much more than a small feature.
An easier option is to use a mobile file upload solution that provides SDKs for iOS, Android, and the web. This gives you a single upload engine with support for camera, gallery, cloud storage, and resumable uploads across all platforms.
Think back to the example from the beginning. A user starts uploading a large photo on Wi-Fi, switches to another app for a moment, and then loses their connection for a short time.
With Intelligent Ingestion, the upload doesn’t have to start over. It adjusts to the slower connection, retries only the parts that failed, and continues automatically when the network returns. This makes it possible to upload files up to 5 GB, even if the connection drops or changes during the upload.
If you’re building this yourself, the mobile SDK docs are a good place to start. You can also read our guide to handling large file uploads and our article on converting images to JPEG if you’re working with different image formats like HEIC and JPG.
Now that we’ve covered both options, let’s quickly recap what matters most.
Conclusion: Design for One Bar of Signal
Good mobile upload design comes down to two things: support all three sources and expect the network to drop.
Resize images before uploading them and split large files into smaller chunks. Make sure uploads can resume after a connection is lost, instead of just showing progress.
Test the upload the way real users will. Turn on airplane mode while a file is uploading and see what happens. If the upload starts again from zero, that’s the first problem to fix, whether you’re building the upload system yourself or using Filestack’s picker and Intelligent Ingestion.
Frequently Asked Questions
Why do mobile uploads fail more than desktop uploads?
Mobile connections hand off between WiFi and cellular, and apps get backgrounded mid-transfer. Both interrupt an upload. Resumable, chunked transfer fixes this by picking up from the last completed chunk instead of restarting.
What sources should a mobile upload flow support?
Camera, gallery, and cloud drives. Each needs its own permission flow, and users expect to switch between all three without friction.
How large can mobile uploads be?
Files up to 5GB can upload reliably over unstable networks using chunked, resumable transfer such as Filestack’s Intelligent Ingestion.
Shefali Jangid is a web developer, technical writer, and content creator with a love for building intuitive tools and resources for developers.
She writes about web development, shares practical coding tips on her blog shefali.dev, and creates projects that make developers’ lives easier.
Read More →