A high-performance file system module for React Native that provides native-speed file operations and network transfers using Swift (iOS) and Kotlin (Android) implementations.
- π File Operations: Read, write, copy, delete, and manage files
- π Directory Management: Create, navigate, and manage directories
- β¬οΈ File Uploads: Upload files with progress tracking and multipart support
- β¬οΈ File Downloads: Download files with progress tracking
- π File Inspection: Check existence, get file stats, and list directory contents
- β‘ Native Performance: Direct Swift/Kotlin implementations for optimal speed
- π± Cross-Platform: Full support for iOS and Android
- π‘οΈ Error Handling: Comprehensive error handling with detailed messages
- πΎ Memory Efficient: Optimized for large files with chunked reading
- React Native: v0.78.0 or higher
- Node.js: 18.0.0 or higher
- Platforms: iOS 12.0+, Android API 21+
# Using bun (recommended)
bun add react-native-nitro-fs [email protected]
# Using npm
npm install react-native-nitro-fs [email protected]
# Using yarn
yarn add react-native-nitro-fs [email protected]
cd ios && pod install
import { NitroFS } from 'react-native-nitro-fs'
// Basic file operations
const exists = await NitroFS.exists('/path/to/file')
const content = await NitroFS.readFile('/path/to/file', 'utf8')
await NitroFS.writeFile('/path/to/file', 'Hello, World!', 'utf8')
// Download with progress
const file = await NitroFS.downloadFile(
'https://example.com/file.txt',
NitroFS.DOWNLOAD_DIR + '/file.txt',
(downloadedBytes, totalBytes) => {
console.log(`Downloading ${(downloadedBytes / totalBytes) * 100}%`)
}
)
// Upload with progress
await NitroFS.uploadFile(
{ name: 'file.txt', mimeType: 'text/plain', path: '/path/to/file.txt' },
{ url: 'https://example.com/upload', method: 'POST', field: 'file' },
(uploadedBytes, totalBytes) => {
console.log(`Uploading ${(uploadedBytes / totalBytes) * 100}%`)
}
)
Access predefined directory paths for different use cases:
// Bundle directory (read-only, app resources)
NitroFS.BUNDLE_DIR
// Documents directory (user data, backed up)
NitroFS.DOCUMENT_DIR
// Cache directory (temporary data, not backed up)
NitroFS.CACHE_DIR
// Downloads directory (user downloads)
NitroFS.DOWNLOAD_DIR
Check if a file or directory exists at the specified path.
// Check if file exists
const fileExists = await NitroFS.exists('/path/to/file.txt')
// Check if directory exists
const dirExists = await NitroFS.exists('/path/to/directory')
Write data to a file. Creates parent directories automatically and performs atomic writes.
// Write text file
await NitroFS.writeFile(
NitroFS.DOCUMENT_DIR + '/config.json',
JSON.stringify({ theme: 'dark' }),
'utf8'
)
// Write with different encoding
await NitroFS.writeFile('/path/to/file.txt', 'Hello World', 'utf8')
Features:
- β Automatic parent directory creation
- β Atomic write operations
- β Disk space validation
- β Comprehensive error handling
Read the contents of a file with optimized memory handling for large files.
// Read text file
const content = await NitroFS.readFile('/path/to/file.txt', 'utf8')
// Read JSON file
const config = JSON.parse(
await NitroFS.readFile('/path/to/config.json', 'utf8')
)
Performance Features:
- π Adaptive chunked reading for large files
- πΎ Memory-efficient handling
β οΈ Automatic size limits for very large files
Copy a file from source to destination.
// Copy file to documents directory
await NitroFS.copyFile(
'/path/to/source.txt',
NitroFS.DOCUMENT_DIR + '/backup.txt'
)
Copy a file or directory recursively.
// Copy entire directory
await NitroFS.copy('/path/to/source', '/path/to/destination')
Delete a file or directory.
// Delete file
await NitroFS.unlink('/path/to/file.txt')
// Delete directory (recursive)
await NitroFS.unlink('/path/to/directory')
Create a directory.
// Create single directory
await NitroFS.mkdir('/path/to/newdir')
// Create nested directories (handled automatically)
await NitroFS.mkdir('/path/to/nested/directories')
Get detailed information about a file or directory.
const stat = await NitroFS.stat('/path/to/file.txt')
console.log({
size: stat.size, // File size in bytes
isDirectory: stat.isDirectory,
isFile: stat.isFile,
modifiedTime: stat.mtime, // Last modified timestamp
createdTime: stat.ctime, // Creation timestamp
})
List contents of a directory.
// List all files and directories
const items = await NitroFS.readdir('/path/to/directory')
console.log('Directory contents:', items)
Rename or move a file or directory.
// Rename file
await NitroFS.rename('/path/to/old.txt', '/path/to/new.txt')
// Move file to different directory
await NitroFS.rename('/path/to/file.txt', '/new/path/file.txt')
Get the directory name from a path.
const dir = NitroFS.dirname('/path/to/file.txt')
// Returns: '/path/to'
Get the filename from a path, optionally removing extension.
const name = NitroFS.basename('/path/to/file.txt')
// Returns: 'file.txt'
const nameWithoutExt = NitroFS.basename('/path/to/file.txt', '.txt')
// Returns: 'file'
Get the file extension from a path.
const ext = NitroFS.extname('/path/to/file.txt')
// Returns: '.txt'
uploadFile(file: NitroFile, uploadOptions: NitroUploadOptions, onProgress?: (uploadedBytes: number, totalBytes: number) => void): Promise<void>
Upload a file to a server with progress tracking and multipart support.
const file = {
name: 'document.pdf',
mimeType: 'application/pdf',
path: NitroFS.DOCUMENT_DIR + '/document.pdf',
}
const uploadOptions = {
url: 'https://api.example.com/upload',
method: 'POST',
field: 'file',
headers: {
'Authorization': 'Bearer your-token',
'X-Custom-Header': 'value',
},
}
await NitroFS.uploadFile(file, uploadOptions, (uploadedBytes, totalBytes) => {
const progress = (uploadedBytes / totalBytes) * 100
console.log(`Upload progress: ${progress.toFixed(1)}%`)
})
downloadFile(serverUrl: string, destinationPath: string, onProgress?: (downloadedBytes: number, totalBytes: number) => void): Promise<NitroFile>
Download a file from a server with progress tracking.
const serverUrl = 'https://example.com/files/document.pdf'
const destinationPath = NitroFS.DOWNLOAD_DIR + '/document.pdf'
const downloadedFile = await NitroFS.downloadFile(
serverUrl,
destinationPath,
(downloadedBytes, totalBytes) => {
const progress = (downloadedBytes / totalBytes) * 100
console.log(`Download progress: ${progress.toFixed(1)}%`)
}
)
console.log('Downloaded file:', downloadedFile)
// Returns: { name: 'document.pdf', mimeType: 'application/pdf', path: '/path/to/file' }
interface NitroFile {
name: string // File name with extension
mimeType: string // MIME type (e.g., 'text/plain', 'application/pdf')
path: string // Full file path
}
interface NitroUploadOptions {
url: string // Upload endpoint URL
method: 'GET' | 'POST' | 'PUT' | 'PATCH' // HTTP method
field: string // Form field name
headers?: Record<string, string> // Custom headers
}
interface NitroFileStat {
size: number // File size in bytes
isDirectory: boolean // True if path is a directory
isFile: boolean // True if path is a file
mtime: number // Last modified timestamp
ctime: number // Creation timestamp
}
type NitroFileEncoding = 'utf8' | 'ascii' | 'base64'
try {
const content = await NitroFS.readFile('/path/to/file.txt', 'utf8')
console.log('File content:', content)
} catch (error) {
if (error.message.includes('File does not exist')) {
console.log('File not found')
} else if (error.message.includes('Permission denied')) {
console.log('No permission to access file')
} else {
console.error('Unexpected error:', error.message)
}
}
// The library automatically handles large files efficiently
const largeFile = await NitroFS.readFile('/path/to/large-file.txt', 'utf8')
// For very large files (>100MB), consider streaming or chunked processing
const stat = await NitroFS.stat('/path/to/large-file.txt')
if (stat.size > 100 * 1024 * 1024) {
// 100MB
console.log('Large file detected, consider streaming')
}
// List all files in documents directory
const files = await NitroFS.readdir(NitroFS.DOCUMENT_DIR)
// Filter for specific file types
const textFiles = files.filter((file) => file.endsWith('.txt'))
// Get file stats for each file
for (const file of files) {
const filePath = `${NitroFS.DOCUMENT_DIR}/${file}`
const stat = await NitroFS.stat(filePath)
console.log(`${file}: ${stat.size} bytes`)
}
const backupFile = async (sourcePath: string) => {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
const backupPath = `${NitroFS.DOCUMENT_DIR}/backup-${timestamp}.txt`
try {
await NitroFS.copyFile(sourcePath, backupPath)
console.log('Backup created successfully')
} catch (error) {
console.error('Backup failed:', error.message)
}
}
Issue: "Permission denied" errors on Android
Solution: Ensure your app has the necessary permissions in AndroidManifest.xml
:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Issue: Memory issues with large files Solution: The library automatically handles large files with chunked reading, but you can implement custom streaming for very large files.
Issue: Upload/download operations hanging Solution: The library includes timeout handling, but you can implement custom timeout logic:
const uploadWithTimeout = async (
file: NitroFile,
options: NitroUploadOptions
) => {
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('Upload timeout')), 30000)
})
return Promise.race([NitroFS.uploadFile(file, options), timeoutPromise])
}
We welcome contributions! Please see our Contributing Guide for details.
# Clone the repository
git clone https://github.com/patrickkabwe/react-native-nitro-fs.git
cd react-native-nitro-fs
# Install dependencies
bun install
# Run example app
cd example
bun install
npx react-native run-ios # or run-android
This project is licensed under the MIT License - see the LICENSE file for details.
Bootstrapped with create-nitro-module.
Made with β€οΈ for the React Native community