A powerful and flexible file upload library for AWS S3, Cloudflare R2, and Apexx Cloud
npm install apexx-uploader-react
npm install apexx-uploader-core
Note: If you're using React, you only need to install apexx-uploader-react
. It includes the core functionality internally.
AWS S3, Cloudflare R2, S3-compatible, Apexx Cloud
Upload multiple files simultaneously with progress tracking
Real-time upload progress and status management
Handle large files with multipart upload support
Cancel individual files or all uploads at once
Robust error handling and reporting
Note: The UI can be created using the hooks and can be customized to your needs. We provide optional pre-built components for quick implementation.
Upload up to 10 files (image/*, video/*, application/pdf, max 50 MB)
Upload up to 10 files (image/*, video/*, application/pdf, max 50 MB)
Supports image/*, video/*, application/pdf up to 50 MB, max 2 files
Supports image/*, video/*, application/pdf up to 50 MB, max 2 files
A powerful hook for handling multiple file uploads with progress tracking, cancellation, and error handling. You need to add server side implementation for the provider you are using.
import { useUploader } from "apexx-uploader-react";
// Call your server side implementation for the provider you are using
const getSignedUrl = async (
operation: string,
params: Record<string, any>
) => {
const response = await fetch(
"http://localhost:3000/presigned-url-aws",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ operation, params }),
}
);
return (await response.json()).url;
};
function FileUploader() {
const {
upload, // Function to start the upload
cancelUpload, // Function to cancel all uploads
cancelFileUpload,// Function to cancel a specific file
reset, // Function to reset the upload state
files, // Current state of all files
totalProgress, // Overall upload progress
status // Current upload status
} = useUploader({
provider: "aws", // or "apexx"
getSignedUrl: getSignedUrl
});
const handleFiles = async (event) => {
const files = Array.from(event.target.files);
await upload(files, {
multipart: true,
partSize: 5 * 1024 * 1024, // 5MB chunks
concurrency: 3,
onProgress: (progress, file) => console.log(`${file.name}: ${progress}%`),
onComplete: (response, file) => console.log(`${file.name} complete`),
onError: (error, file) => console.error(`${file.name} failed`, error)
});
};
return (
<div>
<input type="file" multiple onChange={handleFiles} />
<div>Total Progress: {totalProgress}%</div>
{Object.entries(files).map(([name, file]) => (
<div key={name}>
{name}: {file.progress}%
{file.status === "uploading" && (
<button onClick={() => cancelFileUpload(name)}>Cancel</button>
)}
</div>
))}
<button onClick={() => cancelUpload()}>Cancel All</button>
<button onClick={reset}>Reset</button>
</div>
);
}
interface UploaderConfig {
provider: 'aws' | 'apexx';
getSignedUrl: (operation: string, params: Record<string, any>) => Promise<string>;
}
interface UploadOptions {
key?: string; // Custom key for the file
multipart?: boolean; // Enable multipart upload
partSize?: number; // Size of each part in bytes
concurrency?: number; // Number of concurrent uploads
onProgress?: (progressData: any, file: File) => void; // Progress callback
onComplete?: (response: any, file: File) => void; // Completion callback
onError?: (error: Error, file: File) => void; // Error callback
onStart?: (file: File) => void; // Start callback
}
const aws = require("aws-sdk");
let s3 = new aws.S3({
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
signatureVersion: "v4",
region: "ap-south-1",
});
const getPresignedUrl = async (req, res) => {
try {
const { operation = "putObject" } = req.body;
const { params } = req.body;
const url = await s3.getSignedUrlPromise(operation, {
...params,
Bucket: "your-bucket-name",
});
res.status(200).json({
url,
});
} catch (error) {
console.log(error);
res.status(500).json({
error: error.message,
});
}
};
const ApexxCloud = require("@apexxcloud/sdk-node");
const storage = new ApexxCloud({
accessKey: process.env.APEXXCLOUD_ACCESS_KEY,
secretKey: process.env.APEXXCLOUD_SECRET_KEY,
region: process.env.APEXXCLOUD_REGION,
bucket: process.env.APEXXCLOUD_BUCKET,
});
const getSignedUrl = async (req, res) => {
try {
const { operation } = req.body;
const { params } = req.body; // Contains key, mimeType, totalParts, etc.
const signedUrl = await storage.files.getSignedUrl(
operation,
{
...params,
}
);
res.send({
url: signedUrl,
});
} catch (error) {
res.status(500).send({
error: error.message,
});
}
};
Core implementation for AWS S3 and S3-compatible storage services (including Cloudflare R2).
import { AwsCore } from 'apexx-uploader-core';
// Initialize uploader
const uploader = new AwsCore();
// Simple upload
const response = await uploader.files.upload(file, getSignedUrl, {
onProgress: (progress) => console.log(`Progress: ${progress}%`),
onComplete: (response) => console.log('Complete:', response)
});
// Multipart upload
const response = await uploader.files.uploadMultipart(file, getSignedUrl, {
partSize: 5 * 1024 * 1024, // 5MB chunks
concurrency: 3,
onProgress: (progress) => console.log(`Progress: ${progress}%`),
onComplete: (response) => console.log('Complete:', response)
});
Core implementation for Apexx Cloud storage service, with optimized upload handling.
import { ApexxCloudCore } from 'apexx-uploader-core';
// Initialize uploader
const uploader = new ApexxCloudCore();
// Simple upload
const response = await uploader.files.upload(file, getSignedUrl, {
onProgress: (progress) => console.log(`Progress: ${progress}%`),
onComplete: (response) => console.log('Complete:', response)
});
// Multipart upload
const response = await uploader.files.uploadMultipart(file, getSignedUrl, {
partSize: 5 * 1024 * 1024, // 5MB chunks
concurrency: 3,
onProgress: (progress) => console.log(`Progress: ${progress}%`),
onComplete: (response) => console.log('Complete:', response)
});
interface UploadOptions {
key?: string; // Custom key for the file
partSize?: number; // Size of each part for multipart uploads
concurrency?: number; // Number of concurrent part uploads
onProgress?: (progressData: ProgressData) => void; // Progress callback
onComplete?: (response: Response) => void; // Completion callback
onError?: (error: Error) => void; // Error callback
signal?: AbortSignal; // AbortController signal for cancellation
}
import { useUploader } from "apexx-uploader-react";
// Get signed url from your server
const getSignedUrl = async (
operation: string,
params: Record<string, any>
) => {
const response = await fetch(
"http://localhost:3000/presigned-url-aws",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ operation, params }),
}
);
return (await response.json()).url;
};
function CustomMultiUploader() {
const {
upload,
cancelUpload,
cancelFileUpload,
files,
totalProgress,
status
} = useUploader({
provider: "aws",
getSignedUrl: getSignedUrl
});
const handleFiles = async (event) => {
const files = Array.from(event.target.files);
await upload(files);
};
return (
<div>
<input type="file" multiple onChange={handleFiles} />
<div>Total Progress: {totalProgress}%</div>
{Object.entries(files).map(([name, file]) => (
<div key={name}>
{name}: {file.progress}%
{file.status === "uploading" && (
<button onClick={() => cancelFileUpload(name)}>
Cancel
</button>
)}
</div>
))}
</div>
);
}
import { ApexxCloudCore, AwsCore } from 'apexx-uploader-core';
// Initialize uploader
const uploader = new AwsCore(); // or new ApexxCloudCore()
// Simple upload
const response = await uploader.files.upload(file, getSignedUrl, {
onProgress: (progress) => console.log(`Progress: ${progress}%`),
onComplete: (response) => console.log('Complete:', response)
});
We provide optional pre-built components for quick implementation. These components are built using our hooks and can serve as examples for building your own custom components. You can find the source code for these components on GitHub.
// Using pre-built components
import { UploadDashboard } from "../components/uploadDashboard";
import { UploaderButton } from "../components/uploaderButton";
// Dashboard component with detailed UI
<UploadDashboard
provider="aws"
getSignedUrl={getSignedUrl}
accept={["image/*"]}
maxSize="50 MB"
onComplete={(response) => console.log("Complete:", response)}
/>
// Simple button component
<UploaderButton
provider="aws"
getSignedUrl={getSignedUrl}
accept={["image/*"]}
maxSize="50 MB"
onComplete={(response) => console.log("Complete:", response)}
/>