Skip to Content
MobileReact Native

React Native Integration

This guide explains how to integrate FileZen with React Native (CLI) applications. We recommend using our dedicated SDK packages for the best experience.

📁 Code Example: View the complete working example at github.com/FileZen/filezen/tree/main/apps/expo-app 

Installation

Install the required FileZen packages and file pickers for a React Native project:

You may need to follow additional linking and setup steps for these native modules. See the react-native-document-picker  and react-native-image-picker  docs for details.

Setup

1. Environment Configuration

Set your FileZen API key as an environment variable. This can be done in your local .env file during development or as a system environment variable in production.

.env
FILEZEN_API_KEY=your_api_key_here

The FileZen SDK automatically detects the FILEZEN_API_KEY environment variable for server-side operations, so no additional configuration is needed in your API routes.

2. Provider Setup

Choose between two providers based on your needs:

Option A: ZenStorageProvider (Direct Upload)

For direct uploads to FileZen without a server:

App.tsx
import { ZenStorageProvider } from '@filezen/react'; export default function App() { return ( <ZenStorageProvider apiKey="your-filezen-api-key" // Optional: can use FILEZEN_API_KEY env variable > {/* Your app components */} </ZenStorageProvider> ); }

Option B: ZenClientProvider (Server Integration)

For server-side presigned URL generation:

App.tsx
import { ZenClientProvider } from '@filezen/react'; export default function App() { return ( <ZenClientProvider signUrl="https://your-server.com/api/filezen/sign" // Your server endpoint > {/* Your app components */} </ZenClientProvider> ); }

Provider Comparison: ZenStorageProvider is simpler for direct uploads, while ZenClientProvider requires a server but keeps your API key secure on the backend.

Using FileZen in React Native

Basic File Upload Component

Create a component that handles file uploads using React Native file pickers:

components/FileUpload.tsx
import { useFileZen } from '@filezen/react'; import DocumentPicker from 'react-native-document-picker'; import { launchImageLibrary } from 'react-native-image-picker'; import React, { useState } from 'react'; import { Alert, Text, TouchableOpacity, View } from 'react-native'; export default function FileUpload() { const { upload } = useFileZen(); const [uploading, setUploading] = useState(false); const pickAndUploadImage = async () => { try { const result = await launchImageLibrary({ mediaType: 'photo' }); if (result.didCancel || !result.assets || !result.assets[0]) return; const asset = result.assets[0]; setUploading(true); await upload(asset.uri, { name: asset.fileName || `image_${Date.now()}.jpg`, folder: 'mobile-uploads', listener: { onComplete: () => { setUploading(false); Alert.alert('Success', 'Upload complete!'); }, onError: (upload, error) => { setUploading(false); Alert.alert('Error', error.message); }, }, }); } catch (error) { Alert.alert('Error', 'Failed to pick image'); } }; const pickAndUploadDocument = async () => { try { const res = await DocumentPicker.pickSingle({ type: DocumentPicker.types.allFiles }); setUploading(true); await upload(res.uri, { name: res.name, folder: 'mobile-uploads', listener: { onComplete: () => { setUploading(false); Alert.alert('Success', 'Upload complete!'); }, onError: (upload, error) => { setUploading(false); Alert.alert('Error', error.message); }, }, }); } catch (error) { if (!DocumentPicker.isCancel(error)) { Alert.alert('Error', 'Failed to pick document'); } } }; return ( <View> <TouchableOpacity onPress={pickAndUploadImage} disabled={uploading}> <Text>📷 Pick & Upload Image</Text> </TouchableOpacity> <TouchableOpacity onPress={pickAndUploadDocument} disabled={uploading}> <Text>📄 Pick & Upload Document</Text> </TouchableOpacity> {uploading && <Text>Uploading...</Text>} </View> ); }

Using ZenClientProvider (Server Integration)

If you’re using ZenClientProvider for server-side integration:

components/FileUpload.tsx
import { useZenClient } from '@filezen/react'; import { launchImageLibrary } from 'react-native-image-picker'; import React, { useState } from 'react'; import { Alert, Text, TouchableOpacity, View } from 'react-native'; export default function FileUpload() { const { upload } = useZenClient(); const [uploading, setUploading] = useState(false); const pickAndUploadImage = async () => { try { const result = await launchImageLibrary({ mediaType: 'photo' }); if (result.didCancel || !result.assets || !result.assets[0]) return; const asset = result.assets[0]; setUploading(true); await upload(asset.uri, { name: asset.fileName || `image_${Date.now()}.jpg`, folder: 'mobile-uploads', listener: { onComplete: () => { setUploading(false); Alert.alert('Success', 'Upload complete!'); }, onError: (upload, error) => { setUploading(false); Alert.alert('Error', error.message); }, }, }); } catch (error) { Alert.alert('Error', 'Failed to pick image'); } }; return ( <View> <TouchableOpacity onPress={pickAndUploadImage} disabled={uploading}> <Text>📷 Pick & Upload Image</Text> </TouchableOpacity> {uploading && <Text>Uploading...</Text>} </View> ); }

Advanced Upload with Progress Tracking

components/AdvancedUpload.tsx
import { useFileZen } from '@filezen/react'; import { launchImageLibrary } from 'react-native-image-picker'; import React, { useState } from 'react'; import { Alert, Text, TouchableOpacity, View } from 'react-native'; export default function AdvancedUpload() { const { upload } = useFileZen(); const [uploading, setUploading] = useState(false); const [progress, setProgress] = useState(0); const uploadWithProgress = async () => { try { const result = await launchImageLibrary({ mediaType: 'photo' }); if (result.didCancel || !result.assets || !result.assets[0]) return; const asset = result.assets[0]; setUploading(true); setProgress(0); await upload(asset.uri, { name: asset.fileName || `image_${Date.now()}.jpg`, folder: 'mobile-uploads', metadata: { userId: '12345', uploadSource: 'mobile-app' }, listener: { onStart: () => { console.log('Upload started'); }, onProgress: (upload, progress) => { setProgress(progress.percent || 0); console.log(`Progress: ${progress.percent}%`); }, onComplete: (upload) => { setUploading(false); setProgress(100); Alert.alert('Success', `Upload complete! URL: ${upload.file?.url}`); }, onError: (upload, error) => { setUploading(false); setProgress(0); Alert.alert('Error', `Upload failed: ${error.message}`); }, }, }); } catch (error) { Alert.alert('Error', 'Failed to pick image'); } }; return ( <View> <TouchableOpacity onPress={uploadWithProgress} disabled={uploading}> <Text>📷 Upload with Progress</Text> </TouchableOpacity> {uploading && ( <View> <Text>Uploading... {progress.toFixed(0)}%</Text> </View> )} </View> ); }

Configuration Options

Provider Comparison

FeatureZenStorageProviderZenClientProvider
Upload MethodDirect to FileZenDirect to FileZen
API KeyRequired (client-side)Server-side only
Server RequiredNoYes (for generating signed URLs)
Use CaseSimple apps, prototypesProduction apps with custom logic

Image Resizing (Built-in)

FileZen automatically resizes images on-the-fly using URL parameters:

// Original image <Image source={{ uri: upload.file?.url }} /> // Resized thumbnail (120x120, cover fit) <Image source={{ uri: `${upload.file?.url}?width=120&height=120&fit=cover` }} />

For all available resizing parameters, see the Dynamic Image Documentation .

The upload() method uploads files directly to FileZen from the client side. This reduces traffic usage on your server since files don’t pass through your backend.

Last updated on
© 2026 FileZen. All rights reserved.