evodeus-b2-react
v0.1.2
Published
Modern React file upload components with drag & drop, progress tracking, automatic image resizing, and Cloudflare R2 integration
Maintainers
Readme
React File Upload Components
Modern, accessible React file upload components with drag & drop support, progress tracking, automatic image resizing, and Cloudflare R2 integration.
Components
- FileUpload - General purpose file upload component
- PhotoUpload - Advanced photo upload with gallery view and multiple versions
- SimplePhotoUpload - Photo upload with FileUpload interface but automatic resizing
Features
- 🎯 Drag & Drop - Intuitive file dropping interface
- 📊 Progress Tracking - Real-time upload progress with visual feedback
- 🖼️ Automatic Image Resizing - Creates thumbnail, preview, and original versions
- 🔒 File Validation - Size and type validation with customizable limits
- 🎨 Customizable - Tailwind CSS styling with className override support
- ♿ Accessible - Built with accessibility best practices
- 🔧 TypeScript - Full TypeScript support with exported types
- ☁️ Cloudflare R2 - Optimized for Cloudflare R2 storage via worker proxy
Installation
npm install evodeus-b2-reactPeer Dependencies
Make sure you have these installed in your project:
npm install react react-domBasic Usage
FileUpload - General Purpose
import { FileUpload } from 'evodeus-b2-react'
import 'evodeus-b2-react/style.css'
function App() {
return (
<FileUpload
workerUrl="https://up.evodeus.xyz"
onUploadComplete={(fileUrl, fileName) => {
console.log('Upload complete:', { fileUrl, fileName })
}}
onUploadError={(error) => {
console.error('Upload error:', error)
}}
maxFileSize={10}
acceptedFileTypes={['image/*', 'application/pdf']}
/>
)
}SimplePhotoUpload - Photo Upload with FileUpload Interface
import { SimplePhotoUpload } from 'evodeus-b2-react'
import 'evodeus-b2-react/style.css'
function App() {
return (
<SimplePhotoUpload
workerUrl="https://up.evodeus.xyz"
onUploadComplete={(fileUrl, fileName, allVersions) => {
console.log('Main photo URL:', fileUrl)
console.log('All versions:', allVersions) // original, preview, thumbnail
// Access specific versions
const thumbnail = allVersions?.find(v => v.version === 'thumbnail')
const preview = allVersions?.find(v => v.version === 'preview')
}}
onUploadError={(error) => {
console.error('Upload error:', error)
}}
maxFileSize={10}
/>
)
}PhotoUpload - Advanced Photo Gallery
import { PhotoUpload } from 'evodeus-b2-react'
import 'evodeus-b2-react/style.css'
function App() {
return (
<PhotoUpload
workerUrl="https://up.evodeus.xyz"
onUploadComplete={(uploads) => {
console.log('Photo versions created:', uploads)
// uploads contains all 3 versions with dimensions and URLs
}}
onUploadError={(error) => {
console.error('Upload error:', error)
}}
maxFileSize={10}
/>
)
}Component Comparison
| Feature | FileUpload | SimplePhotoUpload | PhotoUpload |
|---------|------------|-------------------|-------------|
| Endpoint | /upload | /photo-upload | /photo-upload |
| File Types | Configurable | Images only | Images only |
| Processing | None | Auto-resize (3 versions) | Auto-resize (3 versions) |
| Interface | Generic upload | FileUpload-like | Gallery view |
| Callback | Single URL | Original URL + all versions | All versions array |
| Use Case | General files | Photo upload replacement | Photo galleries |
Props
FileUpload Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| workerUrl | string | required | URL of your Cloudflare Worker |
| onUploadComplete | (fileUrl: string, fileName: string) => void | undefined | Callback when upload succeeds |
| onUploadError | (error: string) => void | undefined | Callback when upload fails |
| maxFileSize | number | 10 | Maximum file size in MB |
| acceptedFileTypes | string[] | ['image/*', 'application/pdf', '.doc', '.docx'] | Accepted file types |
| className | string | undefined | Additional CSS classes |
SimplePhotoUpload Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| workerUrl | string | required | URL of your Cloudflare Worker with /photo-upload |
| onUploadComplete | (fileUrl: string, fileName: string, allVersions?: PhotoUploadResult[]) => void | undefined | Callback with original URL + all versions |
| onUploadError | (error: string) => void | undefined | Callback when upload fails |
| maxFileSize | number | 10 | Maximum file size in MB |
| className | string | undefined | Additional CSS classes |
PhotoUpload Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| workerUrl | string | required | URL of your Cloudflare Worker with /photo-upload |
| onUploadComplete | (uploads: PhotoUploadResult[]) => void | undefined | Callback with all photo versions |
| onUploadError | (error: string) => void | undefined | Callback when upload fails |
| maxFileSize | number | 10 | Maximum file size in MB |
| className | string | undefined | Additional CSS classes |
Styling
All components use Tailwind CSS classes. Import the styles:
import 'evodeus-b2-react/dist/style.css'Or customize with your own classes using the className prop.
Photo Upload Features
Automatic Image Resizing
When using SimplePhotoUpload or PhotoUpload, each uploaded image automatically generates:
- Original: Full-size original image
- Preview: Resized to max 800x600 (maintains aspect ratio)
- Thumbnail: Resized to max 150x150 (maintains aspect ratio)
PhotoUploadResult Interface
interface PhotoUploadResult {
version: 'original' | 'preview' | 'thumbnail'
fileName: string
fileId: string
url: string
fullUrl: string
dimensions: { width: number; height: number }
}Advanced Usage
Custom File Types
<FileUpload
workerUrl="https://your-worker.workers.dev"
acceptedFileTypes={[
'image/jpeg',
'image/png',
'application/pdf',
'.docx',
'.xlsx'
]}
maxFileSize={25}
/>With Custom Styling
<FileUpload
workerUrl="https://your-worker.workers.dev"
className="border-blue-500 bg-blue-50"
onUploadComplete={(url, name) => {
// Handle success
}}
/>Worker Setup
This component requires a Cloudflare Worker for handling uploads. The worker should:
- Accept POST requests to
/upload - Handle multipart f
Development
# Install dependencies
npm install
# Start development server
npm run dev
# Build for production
npm run build
# Preview production build
npm run previewArchitecture
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ React App │───▶│ Cloudflare Worker │───▶│ Backblaze B2 │
│ │ │ │ │ │
│ FileUpload │ │ /upload │ │ File Storage │
│ Component │ │ proxy endpoint │ │ │
└─────────────────┘ └──────────────────┘ └─────────────────┘- React Component sends file to Worker via
/uploadendpoint - Cloudflare Worker authenticates with B2 and proxies the upload
- Worker uploads file to B2 and returns the file URL to React
Note: Files are uploaded through the Worker proxy to avoid CORS issues with direct B2 uploads.
Security Notes
- Files are uploaded directly to B2, not through your server
- The Worker only provides temporary upload URLs
- No sensitive B2 credentials are exposed to the client
- File validation happens on both client and server side
Troubleshooting
Common Issues
- CORS Errors:
- Ensure your Cloudflare Worker has CORS enabled
- Check B2 bucket CORS settings in Backblaze console
- Use the Debug component to test CORS connectivity
- Upload Failures: Check B2 credentials in Worker environment variables
- File Size Limits: Verify both component and B2 bucket limits
- Network Issues: Check Worker URL accessibility
- "Failed to fetch" Error:
- Usually indicates CORS issues
- Test with the Node.js script:
node test-b2-direct.js - Check browser network tab for detailed error info
Debug Mode
Enable console logging to debug upload issues:
const handleUploadError = (error: string) => {
console.error('Upload error:', error)
// Add your error handling logic
}License
MIT License - feel free to use in your projects!
