@gw-intech/upload-it
TypeScript icon, indicating that this package has built-in type declarations

0.3.6 • Public • Published

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-it

Browser 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:

  1. Use the S3 provider for direct client-side uploads
  2. 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:

  1. 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 };
  1. 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
  1. 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

Package Sidebar

Install

npm i @gw-intech/upload-it

Weekly Downloads

31

Version

0.3.6

License

MIT

Unpacked Size

558 kB

Total Files

28

Last publish

Collaborators

  • gw-intech