@athex/react-native-bg-upload
v1.0.1
Published
Background uploader for react native applications
Maintainers
Readme
✨ Features
- 🔄 Resumable: Survives app kills, low memory, and device reboots
- 📦 Chunking: Automatic chunking for large files with resume capability
- 🔁 Retry Logic: Exponential backoff with jitter for transient failures
- 📡 Network Aware: Auto pause/resume on connectivity changes
- 🔐 Secure: Credential refresh hooks, no long-term token storage
- 📱 Native Notifications: Foreground service with progress (Android)
- 💾 Persistent Queue: MMKV-based storage for instant recovery
- 🎣 React Hooks:
useUpload()for seamless integration - 📊 Observable: Progress, completion, error events
- 🧪 Battle Tested: Comprehensive test suite included
📱 Platform Support
| Feature | Android (API 21+) | iOS (11+) | | :--- | :---: | :---: | | Background Uploads | ✅ WorkManager | ✅ URLSession | | App Kill Survival | ✅ | ✅ | | Device Reboot | ✅ | ✅ | | Chunking & Resume | ✅ | ✅ | | Retry & Backoff | ✅ | ✅ | | Progress Notification | ✅ | N/A | | Network Monitoring | ✅ | ✅ |
📦 Installation
npm install react-native-bg-upload react-native-mmkv @react-native-community/netinfo
# or
yarn add react-native-bg-upload react-native-mmkv @react-native-community/netinfoiOS: cd ios && pod install
🚀 Quick Start
import { BgUpload } from 'react-native-bg-upload';
// Start an upload
const taskId = await BgUpload.start({
id: 'video-upload-1',
url: 'https://api.example.com/upload',
path: 'file:///path/to/large-video.mp4',
headers: {
'Authorization': 'Bearer YOUR_TOKEN'
},
chunking: {
enabled: true, // Auto-enabled for files > 5MB
chunkSize: 5 * 1024 * 1024 // 5MB chunks
},
retryPolicy: {
maxAttempts: 5,
baseDelay: 1000,
maxDelay: 30000
},
// Android only
notification: {
enabled: true,
title: 'Uploading Video'
}
});🎣 Using Hooks
import { useUpload } from 'react-native-bg-upload';
function UploadScreen({ taskId }) {
const task = useUpload(taskId);
if (!task) return null;
return (
<View>
<Text>State: {task.state}</Text>
<Text>Progress: {task.progress}%</Text>
<ProgressBar progress={task.progress / 100} />
{task.state === 'UPLOADING' && (
<Button title="Pause" onPress={() => BgUpload.pause(taskId)} />
)}
{task.error && <Text style={{color: 'red'}}>{task.error}</Text>}
</View>
);
}📖 API Reference
BgUpload.start(options): Promise<string>
Start a background upload. Returns the task ID.
Options
| Option | Type | Required | Description |
| :--- | :--- | :---: | :--- |
| id | string | ✅ | Unique task identifier |
| url | string | ✅ | Upload destination URL |
| path | string | ✅ | Absolute file path (file://) |
| method | string | | HTTP method (default: POST) |
| headers | object | | HTTP headers |
| networkType | string | | 'ANY', 'WIFI_ONLY', 'UNMETERED' |
| chunking | object | | Chunking configuration |
| retryPolicy | object | | Retry configuration |
| onCredentialRefresh | function | | Token refresh callback |
| notification | object | | Android notification config |
Chunking Options
{
enabled?: boolean; // Enable chunking (default: true for > 5MB)
chunkSize?: number; // Chunk size in bytes (default: 5MB)
maxConcurrent?: number; // Max concurrent chunks (default: 3)
}Retry Policy
{
maxAttempts?: number; // Max retry attempts (default: 5)
baseDelay?: number; // Base delay in ms (default: 1000)
maxDelay?: number; // Max delay in ms (default: 30000)
jitter?: number; // Random jitter in ms (default: 500)
}Other Methods
BgUpload.cancel(taskId): Cancel uploadBgUpload.pause(taskId): Pause uploadBgUpload.resume(taskId): Resume uploadBgUpload.getPending(): Get all pending uploadsBgUpload.addListener(event, callback): Add event listener
🔐 Security
Credential Refresh
BgUpload.start({
id: 'secure-upload',
url: 'https://api.example.com/upload',
path: filePath,
onCredentialRefresh: async () => {
// Refresh your auth token
const newToken = await refreshAuthToken();
return {
'Authorization': `Bearer ${newToken}`
};
}
});Best Practices
- ✅ Use short-lived signed URLs (S3, Azure)
- ✅ Implement
onCredentialRefreshfor token rotation - ✅ Don't store tokens in upload options (use refresh hook)
- ✅ Use HTTPS only
- ❌ Don't hardcode credentials
🧪 Testing
Running Tests
yarn test # Unit tests
yarn test:integration # Integration tests (requires mock server)Example Test Scenarios
- Large file (1GB+) with chunking
- App kill during upload → resume
- Network offline/online toggle
- Retry on server 500 errors
- Notification cancel action (Android)
See IMPLEMENTATION_NOTES.md for server-side contract.
📝 Implementation Notes
Android
- Uses
WorkManagerfor reliable background execution - Foreground Service with notification during active uploads
- Persists task state to survive process death
- Chunks stored with offset tracking for resume
iOS
- Uses
URL Sessionbackground configuration - OS handles upload continuation when app is killed
- Delegate callbacks for progress/completion
- Task state synced via
UserDefaults
Storage
- Queue: MMKV for instant read/write
- Tasks: Serialized JSON with chunk metadata
- Credentials: Never persisted (use refresh hook)
🤝 Contributing
See CONTRIBUTING.md
📄 License
MIT © 2025
