0.3.6 • Published 6 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