expo-background-streamer
v1.0.0
Published
A powerful background file uploader for Expo/React Native applications
Maintainers
Readme
expo-background-streamer 🚀
A powerful background file uploader and downloader for Expo/React Native applications with encryption support, progress tracking, and robust error handling.
⚠️ Note: This package is actively maintained and tested with the latest Expo SDK.
✨ Features
- 📱 Background transfers - Upload and download files in the background on iOS and Android
- 🔒 Encryption support - Optional AES encryption for secure file transfers
- 🗜️ Compression - Built-in compression to reduce transfer times
- 📊 Real-time progress - Detailed progress tracking with speed and ETA
- 🎯 Promise-based API - Simple, modern JavaScript API
- 🔄 Automatic retry - Built-in retry logic for failed transfers
- 📝 TypeScript support - Full TypeScript definitions included
- 🎨 Customizable notifications - Native progress notifications
- 🚀 Streaming transfers - No temporary files needed
- 📱 Cross-platform - Works on both iOS and Android
📦 Installation
npx expo install expo-background-streamer🚀 Quick Start
Basic Upload
import ExpoBackgroundStreamer from "expo-background-streamer";
const uploadId = await ExpoBackgroundStreamer.startUpload({
url: "https://your-upload-endpoint.com/upload",
path: "/path/to/your/file.mp4",
headers: {
"Content-Type": "application/octet-stream",
Authorization: "Bearer your-token",
},
});
console.log(`Upload started with ID: ${uploadId}`);Basic Download
const downloadId = await ExpoBackgroundStreamer.startDownload({
url: "https://example.com/large-file.zip",
path: "/path/to/save/file.zip",
});
console.log(`Download started with ID: ${downloadId}`);With Progress Tracking
// Listen for upload progress
const uploadSub = ExpoBackgroundStreamer.addListener(
"upload-progress",
(event) => {
console.log(`Upload: ${event.progress}% - ${event.speed} bytes/s`);
console.log(`ETA: ${event.estimatedTimeRemaining}s`);
}
);
// Listen for download progress
const downloadSub = ExpoBackgroundStreamer.addListener(
"download-progress",
(event) => {
console.log(`Download: ${event.progress}% - ${event.speed} bytes/s`);
}
);
// Clean up listeners
uploadSub.remove();
downloadSub.remove();🔐 Encryption Example
import * as Crypto from "expo-crypto";
import { Buffer } from "buffer";
// Generate encryption keys
const key = await Crypto.getRandomBytesAsync(32);
const nonce = await Crypto.getRandomBytesAsync(16);
const uploadId = await ExpoBackgroundStreamer.startUpload({
url: "https://your-secure-endpoint.com/upload",
path: "/path/to/sensitive-file.pdf",
encryption: {
enabled: true,
key: Buffer.from(key).toString("hex"),
nonce: Buffer.from(nonce).toString("hex"),
},
});📚 API Reference
Methods
startUpload(options: UploadOptions): Promise<string>
Starts a background upload and returns the upload ID.
interface UploadOptions {
url: string; // Upload endpoint URL
path: string; // Local file path
method?: string; // HTTP method (default: "POST")
headers?: Record<string, string>; // HTTP headers
customTransferId?: string; // Custom transfer ID
appGroup?: string; // iOS app group identifier
encryption?: EncryptionOptions; // Encryption settings
compression?: CompressionOptions; // Compression settings
}startDownload(options: DownloadOptions): Promise<string>
Starts a background download and returns the download ID.
interface DownloadOptions {
url: string; // Download URL
path: string; // Local save path
headers?: Record<string, string>; // HTTP headers
customTransferId?: string; // Custom transfer ID
appGroup?: string; // iOS app group identifier
encryption?: EncryptionOptions; // Encryption settings
compression?: CompressionOptions; // Compression settings
}cancelUpload(uploadId: string): Promise<void>
Cancels an ongoing upload.
cancelDownload(downloadId: string): Promise<void>
Cancels an ongoing download.
getAllActiveTransfers(): Promise<{uploads: Record<string, string>, downloads: Record<string, string>}>
Gets all currently active transfers.
getFileInfo(path: string): Promise<FileInfo>
Gets detailed information about a file.
interface FileInfo {
exists: boolean;
size: number;
name: string;
extension: string;
mimeType: string;
}Encryption Options
interface EncryptionOptions {
enabled: boolean; // Enable/disable encryption
key: string; // Hex-encoded encryption key (32 bytes)
nonce: string; // Hex-encoded nonce (16 bytes)
}Compression Options
interface CompressionOptions {
enabled: boolean; // Enable/disable compression
}Events
Subscribe to transfer events using addListener():
Upload Events
upload-progress- Progress updates during upload{ uploadId: string; progress: number; // 0-100 bytesWritten: number; totalBytes: number; speed: number; // bytes per second estimatedTimeRemaining: number; // seconds }upload-complete- Upload completed successfully{ uploadId: string; response: string; responseHeaders: Record<string, string>; responseCode: number; totalBytes: number; duration: number; // seconds }upload-cancelled- Upload was cancelled{ uploadId: string; bytesWritten: number; totalBytes: number; reason?: string; }
Download Events
download-progress- Progress updates during downloaddownload-complete- Download completed successfullydownload-cancelled- Download was cancelled
Error & Debug Events
error- Error occurred during transferdebug- Debug information (info, warn, error, debug levels)
🏗️ Platform-Specific Notes
iOS
- Requires background fetch capability in your
app.json:{ "expo": { "ios": { "backgroundModes": ["background-fetch", "background-processing"] } } } - Supports background transfers even when app is terminated
- Progress notifications shown in notification center
- Supports iOS app groups for shared container access
Android
- Requires foreground service permission in your
app.json:{ "expo": { "android": { "permissions": ["FOREGROUND_SERVICE", "WAKE_LOCK"] } } } - Supports background transfers with Doze mode optimization
- Progress notifications shown in notification center
- Works with Android's background execution limits
🧪 Test Server
An example Express.js backend that accepts upload and download requests via streaming is available in /test_server/. This server can be used for testing the package functionality during development.
🔧 Development Setup
- Clone the repository
- Install dependencies:
npm install - Build the module:
npm run build - Run the example app:
cd example && npm install && npx expo start
🤝 Contributing
I welcome contributions! Please see my Contributing Guide for details.
Development Workflow
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Update documentation
- Submit a pull request
📄 License
MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- I was inspired by android-upload-service and VydiaRNFileUploader
- Built with ❤️ for the Expo community
📞 Support
- 🐛 Bug reports: GitHub Issues
- 💬 Questions: GitHub Discussions
- 📧 Email: [email protected]
