@lachuuuk/react-native-file-downloader
v1.0.0
Published
Zero-dependency file downloader for React Native with custom headers, progress tracking, retry, resume, app-folder/subfolder, a 'save to…' picker, and multi-platform storage support
Maintainers
Readme
React Native File Downloader
A zero-dependency React Native package for downloading files with advanced features like custom headers, progress tracking, automatic retry, resume capability, and multi-platform storage support.
🎯 Features
- ✅ Download files from HTTP/HTTPS URLs
- ✅ Custom HTTP headers (auth tokens, API keys)
- ✅ Real-time progress tracking (bytes, %, speed, ETA)
- ✅ Status-bar progress notification (Android)
- ✅ Save into an app-named folder or any subfolder
- ✅ Native "Save to…" picker (Android SAF / iOS Files)
- ✅ Automatic retry with exponential backoff (max 3 retries)
- ✅ Resume interrupted downloads
- ✅ Multiple storage locations (Downloads, Documents, Cache, Custom)
- ✅ Automatic permission handling (Android & iOS)
- ✅ Smart file naming with timestamps
- ✅ File-manager visibility (Android MediaStore)
- ✅ Zero external dependencies
📱 Platform Support
- Android: 5.0+ (API 21+)
- iOS: 11.0+
- Bare React Native or Expo dev build (not Expo Go — it contains native code).
🚀 Quick Start
Installation
npm install @lachuuuk/react-native-file-downloader
# iOS:
cd ios && pod installAndroid autolinks automatically. Requires a native rebuild after install (
npx react-native run-android/run-ios, ornpx expo run:*).
Basic Usage
import { DownloadManager } from '@lachuuuk/react-native-file-downloader';
DownloadManager.download(
{ url: 'https://example.com/file.pdf' },
{
onProgress: (p) => console.log(`${p.percentage}%`),
onSuccess: (r) => console.log(`Downloaded: ${r.filePath}`),
onError: (e) => console.error(e.message),
}
);With Custom Headers
DownloadManager.download(
{
url: 'https://api.example.com/secure-file.zip',
headers: {
'Authorization': `Bearer ${token}`,
'X-API-Key': apiKey,
},
storageLocation: 'documents'
},
{
onSuccess: (result) => console.log(result.filePath),
onError: (error) => console.error(error.message),
}
);Status-bar progress notification (Android)
import { PermissionsAndroid, Platform } from 'react-native';
// Android 13+ requires the notification permission.
if (Platform.OS === 'android' && Number(Platform.Version) >= 33) {
await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);
}
DownloadManager.download(
{
url: 'https://example.com/large.zip',
showNotification: true,
notificationTitle: 'Downloading report',
},
{ onSuccess: (r) => console.log(r.filePath) }
);Save into an app-named folder (or a custom subfolder)
DownloadManager.download(
{
url: 'https://example.com/invoice.pdf',
storageLocation: 'downloads',
useAppFolder: true, // → Download/<YourAppName>/invoice.pdf
// subfolder: 'Invoices' // → Download/Invoices/invoice.pdf (takes precedence)
},
{ onSuccess: (r) => console.log(r.filePath) }
);Let the user choose where to save (native picker)
import { DownloadManager, StorageHandler } from '@lachuuuk/react-native-file-downloader';
DownloadManager.download(
{ url: 'https://example.com/report.pdf', storageLocation: 'cache' },
{
onSuccess: async (r) => {
// Android → "Save to…" (SAF); iOS → "Save to Files".
const res = await StorageHandler.saveWithPicker(r.filePath, 'report.pdf');
console.log(res.saved ? `Saved to ${res.uri}` : 'User cancelled');
},
}
);📚 Documentation
- docs/API.md — Complete API reference (methods, props, types, error codes)
- example/App.tsx — Runnable example: download, progress, pause/resume/cancel, directory picker, permissions
- IMPLEMENTATION_STATUS.md — What's implemented and verified
📋 Core API
DownloadManager
// Start a download
DownloadManager.download(config: DownloadConfig, callbacks: DownloadCallbacks): string
// Control downloads
DownloadManager.pause(downloadId: string): Promise<void>
DownloadManager.resume(downloadId: string): Promise<void>
DownloadManager.cancel(downloadId: string): Promise<void>
DownloadManager.getStatus(downloadId: string): Promise<DownloadProgress>StorageHandler
StorageHandler.getStoragePaths(): Promise<StoragePath[]>
StorageHandler.createCustomFolder(name: string): Promise<string>
StorageHandler.deleteFile(path: string): Promise<void>
StorageHandler.fileExists(path: string): Promise<boolean>PermissionManager
PermissionManager.checkPermissions(): Promise<boolean>
PermissionManager.requestPermissions(): Promise<boolean>🏗️ Architecture
TypeScript Layer (DownloadManager, StorageHandler, PermissionManager)
↓
Native Module Bridge
↓
Platform-Specific (Kotlin + Swift)
↓
Native APIs🔒 Security
- ✅ HTTPS support and validation
- ✅ Input validation and sanitization
- ✅ Path traversal protection
- ✅ Timeout protection (30s default)
- ✅ Secure header transmission
📊 Performance
- Chunk-based streaming (64KB default)
- Non-blocking progress updates
- Efficient memory usage for large files
- Exponential backoff retry strategy
🆘 Error Handling
Retryable Errors (Auto-retry)
- Network errors
- Timeouts
- 5xx server errors
Non-Retryable Errors
- Invalid URL (4xx)
- Permission denied
- Storage full
- Invalid path
📝 License
MIT
🙏 Contributing
Pull requests welcome! Please read our contributing guidelines.
📮 Support
For issues and questions, please open an issue on GitHub.
Status: ✅ Implemented (TypeScript + Android/Kotlin + iOS/Swift), type-checked, and unit-tested
Version: 1.0.0
Last Updated: 2026-05-25
