rn-file-toolkit

The ultimate, unified native file management toolkit for React Native & Expo.

npm version npm downloads TypeScript
Get Started View on GitHub

Why rn-file-toolkit?

Most React Native file solutions are fragmented or lightly maintained. rn-file-toolkit gives you a unified, TurboModule-compatible API utilizing OS-native managers for reliable operations.

React Hooks Ready

Built-in state management with useDownload for progress, speeds, and ETA.

Background Persistence

Downloads and uploads survive app suspension with automatic re-attachment.

Smart Queueing

Cap concurrency and set priorities globally without touching native code.

Zero-Dependency Zip

Compress and extract using native java.util.zip and iOS zlib.

Installation

Install the library using your preferred package manager:

# npm
npm install rn-file-toolkit

# yarn
yarn add rn-file-toolkit

# pnpm
pnpm add rn-file-toolkit

(Optional) If you are not using Expo or an auto-linking setup, run pod install in your ios directory.

Quick Start: useDownload

The easiest way to manage a download inside a React component. Get status, rich progress (with speed & ETA), and full controls instantly.

import React from 'react';
import { View, Text, Button } from 'react-native';
import { useDownload } from 'rn-file-toolkit';

export default function DownloadScreen() {
  const { start, pause, resume, cancel, status, progress, result } = useDownload();

  return (
    <View style={{ padding: 20 }}>
      <Button
        title="Start Download"
        onPress={() =>
          start({
            url: 'https://example.com/large-video.mp4',
            destination: 'documents',
          })
        }
      />

      {status === 'downloading' && progress && (
        <View style={{ marginTop: 20 }}>
          <Text>Progress: {progress.percent.toFixed(1)}%</Text>
          <Text>Speed: {(progress.speedBps / 1024 / 1024).toFixed(2)} MB/s</Text>
          <Text>ETA: {progress.etaSeconds.toFixed(0)} seconds</Text>
          
          <View style={{ flexDirection: 'row', gap: 10, marginTop: 10 }}>
            <Button title="Pause" onPress={pause} />
            <Button title="Cancel" onPress={cancel} color="red" />
          </View>
        </View>
      )}

      {status === 'done' && <Text style={{ color: 'green' }}>Saved: {result?.filePath}</Text>}
      {status === 'error' && <Text style={{ color: 'red' }}>Error: {result?.error}</Text>}
    </View>
  );
}

Background Downloads

For programmatic, queue-aware background downloads outside of React components.

import { download } from 'rn-file-toolkit';

const result = await download({
  url: 'https://example.com/file.pdf',
  fileName: 'report.pdf', // Optional custom filename
  destination: 'documents', // 'downloads' | 'cache' | 'documents'
  background: true, // Survive app suspension
  headers: { Authorization: 'Bearer token' },
  queue: true, // Join the managed queue
  priority: 'high', // 'high' | 'normal'
  downloadId: 'my-unique-id', // Optional custom ID for tracking
  notificationTitle: 'Downloading report…', // Android notification
  notificationDescription: 'Please wait',
  checksum: { hash: 'abc123...', algorithm: 'sha256' }, // Verify integrity
  retry: {
    attempts: 3,
    delay: 1000,
    onRetry: (attempt, error) => console.warn(`Retry #${attempt}: ${error}`),
  },
  onProgress: (p) => console.log(`${p.percent.toFixed(1)}% downloaded`),
});

console.log(result.filePath); // Path to the downloaded file

Download Controls

Pause, resume, or cancel any active download by its ID—works both inside and outside React components.

import {
  download,
  pauseDownload,
  resumeDownload,
  cancelDownload,
} from 'rn-file-toolkit';

// Start a download with a known ID
const result = download({
  url: 'https://example.com/large-video.mp4',
  downloadId: 'video-1',
  destination: 'documents',
});

// Later… pause, resume, or cancel by ID
await pauseDownload('video-1');
await resumeDownload('video-1');
await cancelDownload('video-1');

Multipart Uploads

Robust, memory-efficient multipart file uploading for large media or documents.

import { upload } from 'rn-file-toolkit';

const result = await upload({
  url: 'https://api.example.com/v1/upload',
  filePath: '/path/to/local/image.jpg',
  fieldName: 'file',
  headers: { Authorization: 'Bearer token' },
  parameters: { userId: '123', folder: 'avatars' },
  uploadId: 'upload-1', // Optional custom ID for tracking
  onProgress: (percent) => console.log(`Uploading: ${percent}%`),
});

console.log(result.status); // HTTP status code
console.log(result.data); // Server response body

Queue Management

Control download concurrency globally and inspect the queue state.

import { setQueueOptions, getQueueStatus, getBackgroundDownloads } from 'rn-file-toolkit';

// Set the maximum number of simultaneous downloads
setQueueOptions({ maxConcurrent: 3 });

// Inspect the queue at any time
const status = getQueueStatus();
console.log(status.active); // Currently downloading
console.log(status.pending); // Waiting in queue
console.log(status.maxConcurrent); // Concurrency cap

// Retrieve all background downloads currently running
const active = await getBackgroundDownloads();
console.log(active); // Array of background download descriptors

File System (FS)

Perform native filesystem operations securely. Available via the namespaced fs object.

import { fs } from 'rn-file-toolkit';

// Check & Inspect
const exists = await fs.exists('/path/to/data.json');
const stats = await fs.stat('/path/to/data.json'); // { path, name, size, modified, isDir }

// Read & Write
await fs.writeFile('/path/to/data.txt', 'Hello World', 'utf8');
const content = await fs.readFile('/path/to/data.txt', 'utf8');

// Manage Folders & Files
await fs.mkdir('/path/to/new_folder');
const files = await fs.ls('/path/to/new_folder');
await fs.copyFile('/path/src.txt', '/path/dest.txt');
await fs.moveFile('/path/old.txt', '/path/new.txt');
await fs.deleteFile('/path/unwanted.txt');

Zip & Unzip Archives

Compress and extract archives directly on the device using native java.util.zip (Android) and zlib (iOS).

import { unzip, zip } from 'rn-file-toolkit';

// Extract a downloaded zip
const unzipResult = await unzip('/path/to/bundle.zip', '/path/to/extract-folder');
console.log(unzipResult.files); // List of extracted file paths

// Compress user data before uploading
const zipResult = await zip('/path/to/user-data-folder', '/path/to/backup.zip');
console.log(zipResult.zipPath); // Path to the created archive

Cache Management

Inspect and clear files stored in the cache directory.

import { getCachedFiles, clearCache } from 'rn-file-toolkit';

// List all cached files with metadata
const cache = await getCachedFiles();
cache.files?.forEach((f) => {
  console.log(f.fileName, f.filePath, f.size, f.modifiedAt);
});

// Wipe the entire cache directory
await clearCache();

Media & Utilities

Helpful tools for sharing, opening, and encoding files.

import { saveBase64AsFile, urlToBase64, shareFile, openFile } from 'rn-file-toolkit';

// Base64 to File (accepts raw base64 or data URIs)
await saveBase64AsFile({
  base64Data: 'data:image/png;base64,...',
  destination: 'documents',
  fileName: 'image.png',
});

// URL to Base64 (great for caching small images)
const b64 = await urlToBase64({
  url: 'https://example.com/icon.png',
  headers: { Authorization: 'Bearer token' }, // Optional
});
console.log(b64.dataUri); // Ready-to-use data URI string

// Native Share Sheet
await shareFile({
  filePath: '/path/to/report.pdf',
  title: 'Share report',
  subject: 'Monthly report',
});

// Open with default system app
await openFile({
  filePath: '/path/to/report.pdf',
  mimeType: 'application/pdf',
});

Disk Space

Check available and total device storage.

import { df } from 'rn-file-toolkit';

const space = await df();
if (space.success) {
  console.log(`Free: ${(space.freeBytes! / 1024 / 1024 / 1024).toFixed(2)} GB`);
  console.log(`Total: ${(space.totalBytes! / 1024 / 1024 / 1024).toFixed(2)} GB`);
}

File Appending

Append data to the end of a file without overwriting existing content.

import { appendFile } from 'rn-file-toolkit';

// Append a log line
await appendFile('/path/to/log.txt', 'New log entry\n');

// Append base64 data
await appendFile('/path/to/data.bin', base64String, 'base64');

File Hashing

Compute the MD5, SHA-1, or SHA-256 hash of any file on disk.

import { hash } from 'rn-file-toolkit';

const result = await hash('/path/to/file.zip', 'sha256');
if (result.success) {
  console.log('SHA-256:', result.hash);
}

Session Management

Group downloaded files into sessions for batch cleanup. Useful for temporary workflows.

import { session, download } from 'rn-file-toolkit';

// Download files and track them in a session
const result = await download({ url: 'https://example.com/tmp1.pdf', destination: 'cache' });
if (result.filePath) session.add('my-workflow', result.filePath);

// List session files
console.log(session.get('my-workflow')); // ['/path/to/tmp1.pdf']

// Clean up everything when done
await session.clear('my-workflow');

MediaStore / Photos Library

Save files directly to the device's shared media gallery (Photos on iOS, MediaStore on Android).

import { saveToMediaStore } from 'rn-file-toolkit';

const result = await saveToMediaStore({
  filePath: '/path/to/photo.jpg',
  mediaType: 'image',
  album: 'MyApp',  // Optional album/subfolder
});
console.log(result.uri); // content://... (Android) or file path (iOS)
Note: iOS requires NSPhotoLibraryAddUsageDescription in your Info.plist for image/video saves.

Event Listeners

Subscribe to global download and upload lifecycle events. Each listener returns an unsubscribe function.

import { onDownloadComplete, onDownloadError, onDownloadRetry, onUploadProgress } from 'rn-file-toolkit';

// Subscribe
const unsub1 = onDownloadComplete((event) => console.log('Done:', event));
const unsub2 = onDownloadError((event) => console.error('Failed:', event));
const unsub3 = onDownloadRetry((event) => console.warn(`Retry #${event.attempt}`));
const unsub4 = onUploadProgress((event) => console.log(`Upload ${event.progress}%`));

// Clean up
unsub1();
unsub2();
unsub3();
unsub4();

API Reference

Interface Description
DownloadOptions Full configuration for downloading a file (url, priority, background, etc.).
UploadOptions Configuration for multipart uploads.
ProgressInfo Rich real-time download progress payload (percent, speed, eta).
DownloadResult Result returned after a download completes.
FsApi Namespaced filesystem API containing stat, read, write, etc.

Expo Support

rn-file-toolkit works seamlessly with Expo custom development clients (EAS Build / npx expo run:android / npx expo run:ios). Since it contains native code, it is not compatible with Expo Go.

An Expo config plugin is included automatically. No extra configuration is needed in your app.json unless you want to customize permissions.

How does it compare?

Feature rn-file-toolkit react-native-fs / rn-fetch-blob
Background Persistence Yes Spotty / Legacy
Smart Queueing & Concurrency Built-in Write your own
React Hooks (useDownload) Out-of-the-box Manual
Auto-Retries & Resumption Yes Manual
Expo Support Seamless (Custom Dev Client) Requires heavy config