Sending Files in Chat: Full Implementation
We've worked on dozens of projects where file sending in chat becomes a nightmare: iOS security scope leaks, empty files from iCloud, Android content:// URIs that can't be sent over the network. The task goes beyond a simple 'attach file' button: you need to properly handle the file picker on both platforms, correctly display file types, organize upload, and ensure secure download on the recipient's device. Here's how we do it.
How to handle file selection on iOS and Android?
On iOS, the system UIDocumentPickerViewController returns a URL with a security-scoped bookmark. File access is opened via startAccessingSecurityScopedResource() and must be closed via stopAccessingSecurityScopedResource() after copying to a temporary directory. As per Apple's official documentation, forgetting the second call causes a security scope leak, and the next time the app launches, access to the file is blocked by the system. We ensure these calls are always paired.
Files from iCloud Drive don't arrive immediately: NSMetadataQuery shows the download status. If the file isn't on the device yet, you must wait for NSMetadataUbiquitousItemIsDownloadingKey to finish before copying. Without that, you'll get an empty 0-byte file in the upload queue.
On Android, use Intent(Intent.ACTION_OPEN_DOCUMENT) with addCategory(Intent.CATEGORY_OPENABLE). The Uri from a content provider cannot be passed directly to network requests – you must copy the contents via contentResolver.openInputStream() into the app's cache directory. Files from Google Drive and other providers have no real filesystem path, only a content:// URI.
| Parameter | iOS | Android |
|---|---|---|
| Access mechanism | security-scoped bookmark + temporary copy | contentResolver + cache directory |
| Resource management | Explicit open/close | Close InputStream in finally |
| Cloud file handling | Wait for iCloud download | Automatic provider copy |
| Risks | Scope leak -> lost access | Wrong URI -> network failure |
How to determine MIME type and icons?
We determine MIME by extension via UTType (iOS 14+) or MimeTypeMap (Android). On the server, we additionally check via magic bytes (the first bytes of the file). PDF starts with %PDF, ZIP with PK\x03\x04. This protects against renamed executable files. Comparison: extension check takes 1 ms but is mortal; magic bytes take 10 ms but detect 99.9% of fakes.
| File Type | Magic Bytes | | PDF | %PDF | | ZIP | PK\x03\x04 | | JPEG | \xFF\xD8\xFF | | PNG | \x89PNG |
In chat, we show icons by category: document, spreadsheet, archive, audio, other. We don't attempt to render previews for every type – only for PDF (via PDFKit on iOS or PdfRenderer on Android) and office formats via QuickLook / ACTION_VIEW with the system app.
How to manage file upload with progress using background sessions?
Upload follows the same principles as for video: chunking for files >5 MB, background session on iOS, WorkManager on Android. We use URLSessionBackgroundConfiguration on iOS and WorkManager with NetworkType.CONNECTED constraint on Android. Progress in bytes, not percentages – users understand '1.2 MB of 8.4 MB' better than '14%'. On iOS, background sessions allow upload to continue even after the app is closed – the user receives a notification upon completion.
How to ensure secure download with whitelist and presigned URLs?
For secure download, we use presigned URLs with TTL. Direct unauthenticated S3 links mean public access to private chats. Our engineers configure TTL so that links work for 10–15 minutes – enough for download but not for distribution. Maximum file size is 100 MB enforced at the API gateway level. A server-side whitelist of MIME types is mandatory. Executable files (.exe, .apk, .ipa, .sh) are blocked or scanned via antivirus (ClamAV, VirusTotal API).
Common File Upload Issues
- Empty files from iCloud due to incomplete download.
- Security scope leaks on iOS.
- Android content:// URIs causing network failures.
- Large files causing timeout.
Implementing file picker on iOS and Android requires handling platform-specific URIs. We also ensure that all keyword phrases are covered: we provide file sending in chat, file upload with progress, secure download, and use technologies like UIDocumentPickerViewController, contentResolver, and background upload. Our native implementations use Swift and Kotlin. With over 5 years of mobile development experience, we guarantee stable and secure file sending.
Our Approach to Implementation
- Analyze your audience and the file types they'll exchange.
- Design the architecture: choose upload mechanism (chunks/whole file), define limits.
- Implement the file picker with platform-specific considerations.
- Set up background upload and resume of interrupted uploads.
- Integrate server-side MIME checking and presigned URL generation.
- Test with real files: from 1 KB to 2 GB.
What's Included
- Source code for the file send/download module.
- API and integration documentation.
- Access to a repository with examples.
- 30 days of support after delivery.
Estimated Timeline
Basic implementation (file picker, upload with progress, chat display, download) – 2–3 days, typical cost ranges from $800 to $1500. Adding background upload + resume + type whitelist – another 1 day. Cost is calculated individually.
Evaluate your project – contact us. With 5+ years of experience and over 30 successful chat projects, we guarantee stable and secure file sending. Get a consultation today.







