0.3.6 • Published 9 months ago
@gw-intech/upload-it v0.3.6
UploadIt
A flexible and reusable file upload library with support for S3 and filesystem storage.
Features
- 📤 Direct client-side uploads to S3
- 💾 Local filesystem support
- 🔒 Secure server-side credential handling
- 📊 Upload progress tracking
- 🔄 Automatic URL refreshing
- ⚛️ React components and hooks
- 📱 Next.js integration
- 🔌 Provider-based architecture
- 📂 File management utilities
- 📑 Intuitive file listing with icons
Latest Updates (v0.3.6)
- 🎨 Enhanced FileList component with file type icons - Beautiful visual indicators for different file types
- 🖼️ Option to display file icons instead of image previews - More consistent UI and better performance
- 🗂️ File management utilities - Easy-to-use functions for listing, fetching, and deleting files
- 🔄 Improved filesystem integration - Better fallbacks for direct filesystem operations
Installation
npm install @gw-intech/upload-it
# or
yarn add @gw-intech/upload-it
# or
pnpm add @gw-intech/upload-itBrowser Compatibility
The library is designed to work in both browser and Node.js environments:
- S3 Provider: Fully supported in browsers
- Filesystem Provider: Only for server-side use (Node.js)
When using the library in client-side applications (like Vite, Create React App, etc.), you should:
- Use the S3 provider for direct client-side uploads
- Or set up server endpoints for secure uploads
// ✅ Works in browsers
import { UploadButton } from '@gw-intech/upload-it';
function App() {
return (
<UploadButton
provider='s3'
s3={{
region: 'us-east-1',
bucket: 'my-bucket',
credentials: {
// For development only! Use server mode in production
accessKeyId: '...',
secretAccessKey: '...',
},
}}
/>
);
}
// ❌ Won't work in browsers - filesystem requires Node.js
import { UploadButton } from '@gw-intech/upload-it';
function App() {
return (
<UploadButton
provider='filesystem' // ⚠️ This won't work in browsers
filesystem={{
uploadDir: './public/uploads',
publicPath: '/uploads',
}}
/>
);
}Usage
Basic Usage with React Component
import { UploadButton } from '@gw-intech/upload-it';
function MyApp() {
return (
<UploadButton
provider='s3'
s3={{
region: 'us-east-1',
bucket: 'my-bucket',
credentials: {
/* For development only! See secure usage below */
},
}}
onUploadComplete={(files) => console.log('Uploaded files:', files)}
multiple={true}
accept='image/*,.pdf'
/>
);
}Secure Usage with Next.js
When using Next.js, you'll need to import the server-specific routes from the /server subpath:
- Create API routes for uploads:
// app/api/upload/presigned/route.ts
import { presignedUrlRoute } from '@gw-intech/upload-it/server';
export { presignedUrlRoute as POST };
// app/api/upload/complete/route.ts
import { completeUploadRoute } from '@gw-intech/upload-it/server';
export { completeUploadRoute as POST };
// app/api/upload/url/[fileKey]/route.ts
import { getFileUrlRoute } from '@gw-intech/upload-it/server';
export { getFileUrlRoute as GET };- Configure environment variables:
UPLOAD_IT_S3_REGION=us-east-1
UPLOAD_IT_S3_BUCKET=my-bucket
UPLOAD_IT_S3_ACCESS_KEY=your-access-key
UPLOAD_IT_S3_SECRET_KEY=your-secret-key
UPLOAD_IT_S3_FOLDER=uploads- Use the component with server mode:
import { UploadButton } from '@gw-intech/upload-it';
function MyApp() {
return (
<UploadButton
provider='s3'
server={{
mode: 'server',
endpoints: {
getUploadUrl: '/api/upload/presigned',
completeUpload: '/api/upload/complete',
getAccessUrl: '/api/upload/url',
},
}}
onUploadComplete={(files) => console.log('Uploaded files:', files)}
/>
);
}Using with Vite or non-Next.js environments
When using Vite or other build systems, you only need to import from the main package:
import {
UploadButton,
useUploader,
createUploader,
} from '@gw-intech/upload-it';The Next.js specific routes are isolated in the /server subpath to avoid dependency conflicts.
Using the React Hook
import { useUploader } from '@gw-intech/upload-it';
import { useState } from 'react';
function MyUploader() {
const [files, setFiles] = useState([]);
const uploader = useUploader({
provider: 's3',
s3: {
region: 'us-east-1',
bucket: 'my-bucket',
credentials: {
/* ... */
},
},
onSuccess: (uploadedFiles) => {
setFiles(uploadedFiles);
},
});
const handleFileChange = async (e) => {
const selectedFiles = e.target.files;
if (selectedFiles.length > 0) {
await uploader.uploadFiles(Array.from(selectedFiles));
}
};
return (
<div>
<input type='file' multiple onChange={handleFileChange} />
{uploader.isUploading && (
<div>
Uploading... {Object.values(uploader.progress)[0]?.percentage}%
</div>
)}
{files.map((file) => (
<div key={file.key}>
{file.name} -{' '}
<a href={file.url} target='_blank' rel='noopener noreferrer'>
View
</a>
</div>
))}
</div>
);
}Filesystem Storage
import { UploadButton } from '@gw-intech/upload-it';
function MyApp() {
return (
<UploadButton
provider='filesystem'
filesystem={{
uploadDir: './public/uploads',
publicPath: '/uploads',
}}
onUploadComplete={(files) => console.log('Uploaded files:', files)}
/>
);
}Core API (Non-React)
import { createUploader } from '@gw-intech/upload-it';
const uploader = createUploader({
provider: 's3',
s3: {
region: 'us-east-1',
bucket: 'my-bucket',
credentials: {
/* ... */
},
},
onUploadProgress: (file, progress) => {
console.log(`${file.name}: ${progress.percentage}%`);
},
});
async function uploadFile(file) {
try {
const result = await uploader.uploadFile(file);
console.log('File uploaded:', result);
return result;
} catch (error) {
console.error('Upload failed:', error);
}
}Component Props
UploadButton Props
The UploadButton component accepts the following props:
Core Configuration
| Prop | Type | Required | Description |
|---|---|---|---|
provider | 's3' \| 'filesystem' | Yes | Storage provider to use |
s3 | S3Config | Only with s3 provider | S3 configuration |
filesystem | FilesystemConfig | Only with filesystem provider | Filesystem configuration |
server | ServerConfig | No | Server configuration for secure mode |
maxFileSize | number | No | Maximum file size in bytes |
allowedFileTypes | string[] | No | Allowed file types (e.g., 'image/*', '.pdf') |
UI Customization
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
className | string | No | '' | CSS class applied to the button |
buttonText | string | No | 'Upload' | Text displayed on the button |
children | React.ReactNode | No | null | Content to render inside the button |
showProgressDialog | boolean | No | true | Whether to show the progress dialog |
dialogTitle | string | No | 'Upload File' | Title for the progress dialog |
Upload Options
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
multiple | boolean | No | false | Allow multiple file selection |
accept | string | No | undefined | File type filter (e.g., "image/*,.pdf") |
folder | string | No | undefined | Optional folder path for uploaded files |
Callbacks
| Prop | Type | Required | Description |
|---|---|---|---|
onSuccess | (files: FileMetadata[]) => void | No | Called when uploads complete successfully |
onError | (error: Error) => void | No | Called when an error occurs |
Advanced Customization
| Prop | Type | Required | Description |
|---|---|---|---|
renderButton | (props: { onClick: () => void; isUploading: boolean }) => React.ReactNode | No | Custom button rendering |
renderDialog | (props: { isOpen: boolean; onClose: () => void; progress: number; isComplete: boolean; hasErrors: boolean; }) => React.ReactNode | No | Custom dialog rendering |
Configuration Options
Common Options
| Option | Type | Description |
|---|---|---|
provider | 's3' \| 'filesystem' | Storage provider to use |
maxFileSize | number | Maximum file size in bytes |
allowedFileTypes | string[] | Allowed file types (e.g., ['image/*', '.pdf']) |
S3 Provider Options
| Option | Type | Description |
|---|---|---|
region | string | AWS region |
bucket | string | S3 bucket name |
credentials | { accessKeyId: string, secretAccessKey: string } | AWS credentials |
endpoint | string | Custom endpoint (for S3-compatible storage) |
uploadFolder | string | Folder prefix for uploaded files |
Filesystem Provider Options
| Option | Type | Description |
|---|---|---|
uploadDir | string | Directory to store uploaded files |
publicPath | string | Public URL path to access files |
createDirIfNotExist | boolean | Create directory if it doesn't exist |
Server Options
| Option | Type | Description |
|---|---|---|
mode | 'client' \| 'server' | Whether to use client or server mode |
endpoints | { getUploadUrl?: string, completeUpload?: string, getAccessUrl?: string } | API endpoints for server operations |
License
MIT