Skip to content

Repository files navigation

React Native Uploads SDK

The FastPix React Native Uploads SDK provides reliable, resumable, and high-performance uploads for large files in React Native applications. It supports chunked uploads, automatic retries, pause and resume, network recovery, and real-time progress tracking on both Android and iOS.

Please note that this SDK is designed to work only with FastPix and is not a general-purpose uploads SDK.

Table of Contents

Features

  • Chunked Uploads – Upload large files in configurable chunks (5 MB–500 MB).
  • Resumable Uploads – Pause and resume uploads without re-uploading completed chunks.
  • Network Recovery – Automatically pause and resume uploads when connectivity changes.
  • Real-time Progress – Track upload progress with smooth, continuous updates.
  • Automatic Retries – Recover from temporary failures with configurable exponential backoff.
  • File Size Validation – Optionally enforce a maximum file size before uploading.
  • Flexible File URI Support – Accepts file:// URIs and plain filesystem paths, with automatic URL-decoding of percent-encoded paths.
  • Lifecycle Events – Listen to upload progress, state changes, and completion events.

Prerequisites

Generate a signed upload URL

To get started with the SDK, you will need a signed URL.

To make API requests, you'll need a valid Access Token and Secret Key. See the Basic Authentication Guide for details on retrieving these credentials.

Once you have your credentials, use the Upload media from device API to generate a signed URL for uploading media.

What is a Signed URL?

A signed URL is a pre-authenticated URL that allows secure, direct uploads to FastPix storage without exposing your Access Token and Secret Key inside your mobile app. You create the URL on a trusted server (or a short-lived backend call), then hand only that URL to the SDK on the device.

Never ship your Access Token / Secret Key in the app bundle. Generate signed URLs from your backend and return only the signed URL to the client.

Sample Code: Generating a Signed URL

Here is a self-contained service that calls the FastPix Direct Upload API and returns a signed URL. It uses axios and base-64 for the Basic Auth header (the same approach used by the bundled example app in test-example/src/Services/ApiService.ts):

This is your backend/service code, not part of the SDK. Install its helpers with npm install axios base-64. On a Node backend you can drop base-64 and use Buffer.from(...).toString("base64") instead.

importaxiosfrom"axios";importbase64from"base-64";constTOKEN_ID="your_token_id";constSECRET_KEY="your_secret_key";constAPI_BASE_URL="https://api.fastpix.io/v1/on-demand";exportasyncfunctiongenerateSignedUrl(metadata={uploadedBy: "react_native_app"}){constauth=`Basic ${base64.encode(`${TOKEN_ID}:${SECRET_KEY}`)}`;constbody={corsOrigin: "*",pushMediaSettings: {
metadata,accessPolicy: "public",maxResolution: "1080p",},};constresponse=awaitaxios.post(`${API_BASE_URL}/upload`,body,{headers: {"Content-Type": "application/json",Accept: "application/json",Authorization: auth,},});constdata=response.data?.data;if(!data?.url||!data?.uploadId){thrownewError("Failed to generate signed URL");}// { url, uploadId } — pass `url` to FastPixUpload; keep `uploadId` for trackingreturn{url: data.url,uploadId: data.uploadId};}

Integration: create a Signed URL, then Upload

Because endpoint accepts an async factory (() => Promise<string>), you can plug the signed-URL generator straight in. The async factory runs once when start() is called, so the URL is created lazily and stays fresh:

import{FastPixUpload}from"@fastpix/react-native-uploads";import{generateSignedUrl}from"./services/SignedUrlService";exportasyncfunctionuploadVideo(fileUri){constupload=newFastPixUpload({// Factory is invoked at start() — the token stays on your backend.endpoint: async()=>{const{ url }=awaitgenerateSignedUrl({uploadedBy: "react_native_app",fileType: "video",});returnurl;},
fileUri,// file:// URI from your image/video pickerchunkSize: 16*1024,// 16 MB chunksmaxRetries: 3,// retry each failed chunk up to 3 timesretryDelay: 2000,// 2s initial delay, doubling each retrymaxFileSize: 2*1024*1024,// 2 GB limit (in KB); 0 = no limitenableLogs: __DEV__,// logs in development only});upload.on("progress",({ percentage })=>console.log(`${percentage}%`));upload.on("success",()=>console.log("Upload complete!"));upload.on("error",({ message })=>console.error(message));awaitupload.start();returnupload;// keep the ref to pause() / resume() / abort()}

This example uses every constructor option — see Configuration Parameters for the full table with types, defaults, and constraints.

Platform Support

PlatformMinimum version
AndroidAPI 21 (Android 5.0)
iOSiOS 13.0
React Native0.70+

Installation

To install the SDK, use npm or your preferred package manager:

npm install @fastpix/react-native-uploads

The SDK bundles its runtime dependencies (@react-native-community/netinfo, react-native-blob-util, and axios), so there are no peer dependencies to install manually.

iOS — install native pods

The bundled native modules auto-link on React Native 0.70+. After installing the package, run:

cd ios && pod install &&cd ..

Android: No manual linking or extra setup is required — the native modules auto-link.

Basic Usage

Integration

import{FastPixUpload}from"@fastpix/react-native-uploads";constupload=newFastPixUpload({endpoint: "https://storage.googleapis.com/...your-signed-url...",// Replace with the signed URL.fileUri: asset.uri,// file:// URI from your image picker.chunkSize: 5*1024,// Minimum allowed chunk size is 5120KB (5MB).// Additional optional parameters can be specified here as needed});awaitupload.start();

Parameters used above:endpoint, fileUri, chunkSize — see Configuration Parameters for types, defaults, and constraints.

Resumable Uploads: Pause, Resume & Network Recovery

Resumability is the core of this SDK. Every chunk that finishes uploading is acknowledged by the server, so a paused, interrupted, or network-dropped upload always continues from the last server-confirmed offset — completed chunks are never re-sent.

There are two ways an upload can pause:

TriggerHow it happensHow it resumes
User-initiatedYou call upload.pause()You call await upload.resume()
Network-initiatedConnectivity is lost, or the transport switches (Wi-Fi ↔ cellular)The SDK resumes automatically when connectivity returns

Both emit a pause event carrying a reason ('user' or 'network'), so your UI can react appropriately.

Minimal pause / resume flow

import{FastPixUpload}from"@fastpix/react-native-uploads";constupload=newFastPixUpload({endpoint: "https://storage.googleapis.com/...signed-url...",fileUri: asset.uri,chunkSize: 16*1024,// 16 MB chunksmaxRetries: 3,});upload.on("progress",({ percentage })=>console.log(`${percentage}%`));upload.on("pause",({ reason })=>console.log(`Paused (${reason})`));upload.on("resume",({ fromOffset })=>console.log(`Resumed from byte ${fromOffset}`));upload.on("success",()=>console.log("Upload complete!"));awaitupload.start();// …later, from a button press:upload.pause();// pauses immediately, preserving progressawaitupload.resume();// re-syncs the server offset, then continues

Parameters used above:endpoint, fileUri, chunkSize, maxRetries — see Configuration Parameters for types, defaults, and constraints.

Full React component: progress bar with pause / resume / abort

A complete, copy-paste example wiring the resumable lifecycle to UI controls. The same flow is implemented end-to-end in the bundled test-example/ app.

importReact,{useEffect,useRef,useState}from"react";import{View,Text,Button,ActivityIndicator}from"react-native";import{FastPixUpload}from"@fastpix/react-native-uploads";import{generateSignedUrl}from"./services/SignedUrlService";exportfunctionVideoUploader({ fileUri }){constuploadRef=useRef(null);const[percentage,setPercentage]=useState(0);const[state,setState]=useState("IDLE");useEffect(()=>{constupload=newFastPixUpload({endpoint: async()=>(awaitgenerateSignedUrl()).url,// created lazily at start()
fileUri,chunkSize: 16*1024,// 16 MB chunksmaxRetries: 3,retryDelay: 2000,enableLogs: __DEV__,});uploadRef.current=upload;// on() returns an unsubscribe function — collect and clean up on unmount.constoff=[upload.on("progress",({ percentage })=>setPercentage(percentage)),upload.on("stateChange",({ to })=>setState(to)),upload.on("pause",({ reason })=>console.log(reason==="network" ? "Paused — waiting for network…" : "Paused by user"),),upload.on("resume",({ fromOffset })=>console.log(`Resumed from ${fromOffset}`)),upload.on("success",()=>console.log("Upload complete!")),upload.on("error",({ message })=>console.error(message)),];upload.start();return()=>{off.forEach((unsubscribe)=>unsubscribe());upload.abort();// release native resources if the screen unmounts mid-upload};},[fileUri]);constisUploading=state==="UPLOADING"||state==="RESUMED";constisPaused=state==="PAUSED";return(<Viewstyle={{padding: 16,gap: 12}}><Text>{state}{percentage}%</Text>{isUploading&&<ActivityIndicator/>}<Buttontitle="Pause"onPress={()=>uploadRef.current?.pause()}disabled={!isUploading}/><Buttontitle="Resume"onPress={()=>uploadRef.current?.resume()}disabled={!isPaused}/><Buttontitle="Abort"onPress={()=>uploadRef.current?.abort()}disabled={state==="IDLE"}/></View>);}

Parameters used above:endpoint, fileUri, chunkSize, maxRetries, retryDelay, enableLogs — see Configuration Parameters for types, defaults, and constraints.

Automatic network recovery

The SDK automatically resumes uploads when network connectivity is restored. While an upload is in flight the SDK monitors connectivity via @react-native-community/netinfo:

  • Goes offline → the upload pauses and emits pause with reason: 'network' (plus an offline event).
  • Comes back online → the upload resumes automatically from the last confirmed offset (emitting online, then resume).
  • Transport switches (Wi-Fi ↔ cellular) while a socket is mid-flight → the SDK detects the dead connection, re-syncs the server offset, and continues — no stalled upload, no manual retry.

An upload paused by you (reason: 'user') is not auto-resumed on reconnect — that stays under your control, so a user-paused upload never restarts behind their back.

Chunk-Level Retry Tracking

Retries are tracked per individual chunk rather than with a single global counter. Each chunk gets its own budget of maxRetries attempts with exponential back-off, so one flaky chunk can never exhaust the retry allowance of the others.

Benefits

  • No app sluggishness – a single problematic chunk is isolated and doesn't stall the rest of the upload.
  • Better error isolation – a failed chunk never affects the retry limits of chunks that already succeeded.
  • Precise recovery – on a network blip only the in-flight chunk retries; completed chunks are never re-uploaded.

You can observe this live through the chunk events:

upload.on("chunkAttempt",({ chunkIndex, attemptNumber, totalChunkNumbers })=>{console.log(`Chunk ${chunkIndex}/${totalChunkNumbers} — attempt ${attemptNumber}`);});upload.on("chunkAttemptFailure",({ chunkIndex, attemptNumber, error })=>{console.warn(`Chunk ${chunkIndex} failed (attempt ${attemptNumber}/${/* maxRetries */5}): ${error.message}`);});upload.on("chunkSuccess",({ chunkIndex })=>{console.log(`Chunk ${chunkIndex} uploaded`);});

Lifecycle Events Reference

Subscribe to upload lifecycle events using upload.on(event, handler). Each subscription returns a cleanup function, making it easy to use with React's useEffect.

// Upload startedupload.on("started",({ fileSize, endpoint })=>{console.log(`Upload started (${fileSize} bytes) → ${endpoint}`);});// Upload progressupload.on("progress",({ percentage, bytesUploaded, bytesTotal })=>{console.log(`${percentage}% (${bytesUploaded}/${bytesTotal})`);});// Upload state changesupload.on("stateChange",({ from, to })=>{console.log(`${from}${to}`);});// Chunk lifecycleupload.on("chunkAttempt",({ chunkIndex, attemptNumber, totalChunkNumbers })=>{console.log(`Chunk ${chunkIndex}/${totalChunkNumbers} - Attempt ${attemptNumber}`);});upload.on("chunkAttemptFailure",({ chunkIndex, attemptNumber, error })=>{console.warn(`Chunk ${chunkIndex} failed (Attempt ${attemptNumber}): ${error.message}`);});upload.on("chunkSuccess",({ chunkIndex, offset })=>{console.log(`Chunk ${chunkIndex} uploaded (server offset now ${offset})`);});// Upload completedupload.on("success",()=>{console.log("Upload completed successfully");});// Upload failedupload.on("error",({ message, code, retriable })=>{console.error(`${message}${code ? ` [${code}]` : ""} (retriable: ${retriable})`);});// Upload paused/resumedupload.on("pause",({ reason })=>{console.log(`Paused: ${reason}`);});upload.on("resume",({ fromOffset })=>{console.log(`Resumed from offset ${fromOffset}`);});// Upload abortedupload.on("abort",()=>{console.log("Upload aborted");});// Network statusupload.on("offline",()=>{console.log("Network offline");});upload.on("online",()=>{console.log("Network online");});

Supported Events

EventDescription
startedFired when the upload starts.
progressReports upload progress, uploaded bytes, and total bytes.
stateChangeFired whenever the upload state changes.
chunkAttemptFired before each chunk upload attempt.
chunkAttemptFailureFired when a chunk upload attempt fails and will be retried.
chunkSuccessFired after a chunk is uploaded successfully.
successFired when the upload completes successfully.
errorFired when the upload fails with a non-recoverable error.
pauseFired when the upload is paused.
resumeFired when the upload resumes.
abortFired when the upload is cancelled.
offlineFired when network connectivity is lost.
onlineFired when network connectivity is restored.

Upload Control Methods

You can control the upload lifecycle with the following methods:

  • Start an Upload:

    awaitupload.start();// Valid only when state is IDLE
  • Pause an Upload:

    upload.pause();// Valid only when state is UPLOADING; preserves the last acknowledged offset
  • Resume an Upload:

    awaitupload.resume();// Valid only when state is PAUSED; re-syncs the server offset first
  • Abort an Upload:

    upload.abort();// Permanently cancels and releases all resources; emits `abort` before removing listeners

API Reference

FastPixUpload

The main upload class. Construct it with the options below, then drive it with these methods, getters, and events.

Configuration Parameters

The FastPixUpload constructor accepts the following parameters:

NameTypeRequiredDescription
endpointstring or () => Promise<string>RequiredThe signed FastPix upload URL, or an async factory that returns one. The factory is called once at start() — useful when tokens are short-lived.
fileUristringRequiredLocal file path from your file picker. Accepts file:// URIs, plain paths.
chunkSizenumber (in KB)OptionalSize of each chunk in kilobytes. Default is 5120 KB (5 MB). Minimum: 5120 KB (5 MB), Maximum: 512000 KB (500 MB). Must be a multiple of 256 — e.g. any N * 1024 value is safe.
maxRetriesnumberOptionalMaximum retry attempts per failed chunk before the upload fails. Default is 5.
retryDelaynumber (in ms)OptionalInitial delay before the first retry. Each subsequent retry doubles the delay (exponential back-off). Default is 1000.
maxFileSizenumber (in KB)OptionalMaximum allowed file size. 0 means no limit. Files exceeding this fail immediately before any network request. Default is 0.
enableLogsbooleanOptionalEnable SDK-internal debug logging to the console. Recommended for development; disable in production. Default is false.

Example usage of integrating all parameters

import{FastPixUpload}from"@fastpix/react-native-uploads";constupload=newFastPixUpload({endpoint: "https://storage.googleapis.com/...signed-url...",// Signed URL for uploadingfileUri: "file://...File_Path...",// file:// URI to uploadchunkSize: 5*1024,// default is 5 MB per chunkmaxRetries: 3,// Retry each failed chunk up to 3 timesretryDelay: 1000,// Initial 1s delay, doubling each retrymaxFileSize: 200*1024,// 200 MB limitenableLogs: false,// Debug logs in development only});upload.on("started",({ fileSize })=>console.log(`Starting ${fileSize} bytes`));upload.on("progress",({ percentage })=>console.log(`${percentage}%`));upload.on("success",()=>console.log("Upload complete!"));upload.on("error",({ message })=>console.error(message));awaitupload.start();// Control:// upload.pause();// await upload.resume();// upload.abort();

Methods

MethodSignatureDescription
start()() => Promise<void>Starts the upload. Valid only from the IDLE state; otherwise ignored with a warning.
pause()() => voidPauses an in-progress upload, preserving the last acknowledged offset. Valid only from UPLOADING.
resume()() => Promise<void>Resumes a paused upload. Re-syncs the server offset first, then continues. Valid only from PAUSED.
abort()() => voidPermanently cancels the upload and releases native resources. Emits abort, then removes all listeners.
on(event, handler)(event, handler) => () => voidSubscribes to a lifecycle event. Returns an unsubscribe function.
off(event, handler)(event, handler) => voidManually removes a previously registered listener.

Getters

GetterTypeDescription
stateUploadStateThe current state of the upload state machine.
progressUploadProgressSnapshotA point-in-time snapshot of upload progress (bytes, percentage, current chunk).
stateHistoryReadonlyArray<{ from, to, at }>An ordered log of every state transition, each with a timestamp (at).

Types

UploadState

typeUploadState=|"IDLE"// Constructed, not yet started|"STARTED"// start() called, preparing|"UPLOADING"// Actively transferring chunks|"PAUSED"// Paused (by user or network)|"RESUMED"// Transitioning back into UPLOADING|"FAILED"// Stopped with a non-recoverable error|"COMPLETED";// All chunks uploaded successfully

UploadProgressSnapshot

Returned by the progress getter.

PropertyTypeDescription
stateUploadStateCurrent upload state.
bytesUploadednumberBytes transferred and confirmed so far.
bytesTotalnumberTotal size of the file in bytes.
percentagenumberCompletion percentage (0–100).
currentChunkIndexnumberIndex of the chunk currently being processed.

ChunkMeta

Describes the byte range of a single chunk. Exported for consumers that need to reason about chunk boundaries.

PropertyTypeDescription
indexnumberZero-based index of the chunk.
startnumberStart byte offset of the chunk (inclusive).
endnumberEnd byte offset of the chunk (exclusive).
totalSizenumberTotal size of the file in bytes.

For the full list of event payloads, see Supported Events.

Example App

A complete React Native example application is included in the repository to help you get started quickly.

The example demonstrates:

  • Selecting media from the device
  • Creating an upload instance
  • Tracking upload progress
  • Handling upload lifecycle events
  • Pause, resume, and abort operations
  • Network recovery
  • Error handling

Refer to the test-example/ directory for the complete implementation.

Troubleshooting

SymptomLikely causeFix
File is empty or could not be readThe fileUri points to a missing file, or a content:// / asset URI the native layer can't stat.Pass a resolved file:// path or plain filesystem path. Copy picker/asset URIs to a local file first.
File size … exceeds the maximum allowed sizeThe file is larger than maxFileSize (in KB).Increase maxFileSize, or set it to 0 to disable the limit.
chunkSize validation errorchunkSize is outside the allowed range, or not a multiple of 256.Use a value between 5120 KB (5 MB) and 512000 KB (500 MB) that is divisible by 256 (e.g. 16 * 1024).
Upload never starts / start() ignoredstart() was called while the upload was not in the IDLE state.Only call start() from IDLE; use resume() to continue a paused upload.
Upload stalls after switching Wi-Fi ↔ cellularThe in-flight socket died without an offline/online event.The SDK detects the transport switch and resumes from the server-confirmed offset automatically — no action needed.
iOS build fails to find native modulesPods not installed after adding the package.Run cd ios && pod install.
No events firingListeners were attached after abort(), which removes all listeners.Re-attach listeners on a new FastPixUpload instance after an abort.

Enable enableLogs: true in the constructor to see detailed SDK-internal logs while diagnosing issues (disable in production).

Additional References

FastPix HomepageFastPix Dashboard

Detailed Usage

For more detailed steps and advanced usage, please refer to the official FastPix Documentation.

About

FastPix React Native Uploader is a resumable, chunked file upload SDK for iOS and Android with pause/resume, upload progress, and automatic network recovery.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages