VUI File Uploader

A powerful, feature-rich file upload component with drag & drop, progress tracking, file validation, and multiple upload options.

Angular 20+ Drag & Drop Progress Tracking File Validation Multiple Files

✨ Key Features

🗂️

Drag & Drop

Intuitive drag and drop interface with visual feedback and hover states.

📊

Progress Tracking

Real-time upload progress with detailed status information and error handling.

🛡️

File Validation

Comprehensive file validation including size limits, type restrictions, and custom rules.

📦 Installation

Install via npm

npm install @vui/file-uploader

Import in your module

import { VuiUploaderComponent } from '@vui/file-uploader';

@Component({
  standalone: true,
  imports: [VuiUploaderComponent],
  // ...
})

🚀 Basic Usage

Simple File Upload

Live Demo

Click to upload or drag and drop files here

PNG, JPG, GIF up to 10MB

Implementation

@Component({
  standalone: true,
  imports: [VuiUploaderComponent],
  template: `
    <ng-vui-file-uploader
      [multiple]="true"
      [maxSize]="10485760"
      [acceptedTypes]="acceptedTypes"
      [uploadUrl]="'/api/upload'"
      (filesSelected)="onFilesSelected($event)"
      (uploadProgress)="onUploadProgress($event)"
      (uploadComplete)="onUploadComplete($event)"
      (uploadError)="onUploadError($event)">
    </ng-vui-file-uploader>
  `
})
export class MyComponent {
  acceptedTypes = ['image/*', '.pdf', '.doc', '.docx'];

  onFilesSelected(files: FileUploadMetadata[]): void {
    console.log('Files selected:', files);
  }

  onUploadProgress(event: UploadProgressEvent): void {
    console.log(`Upload progress: ${event.progress}%`);
  }

  onUploadComplete(response: any): void {
    console.log('Upload completed:', response);
  }

  onUploadError(error: any): void {
    console.error('Upload error:', error);
  }
}

⚡ Advanced Examples

Custom Upload Configuration

export class CustomUploaderComponent {
  uploadConfig: UploadConfig = {
    uploadUrl: '/api/files/upload',
    maxFileSize: 5 * 1024 * 1024, // 5MB
    allowedTypes: [
      'image/jpeg', 'image/png', 'image/gif',
      'application/pdf',
      'application/msword',
      'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
    ],
    maxFiles: 5,
    autoUpload: false, // Manual upload control
    headers: {
      'Authorization': 'Bearer ' + this.authToken,
      'X-Custom-Header': 'custom-value'
    },
    additionalData: {
      userId: this.currentUser.id,
      category: 'documents'
    }
  };

  // Custom validation rules
  customValidation = (file: File): ValidationResult => {
    // Custom file name validation
    if (file.name.includes(' ')) {
      return {
        valid: false,
        error: 'File names cannot contain spaces'
      };
    }

    // Custom content validation
    if (file.type === 'image/jpeg' && file.size > 2 * 1024 * 1024) {
      return {
        valid: false,
        error: 'JPEG images must be under 2MB'
      };
    }

    return { valid: true };
  };

  onFileValidation(file: File): boolean {
    const result = this.customValidation(file);
    if (!result.valid) {
      this.showError(result.error);
      return false;
    }
    return true;
  }

  // Manual upload control
  startUpload(): void {
    this.uploaderComponent.startUpload();
  }

  pauseUpload(): void {
    this.uploaderComponent.pauseUpload();
  }

  cancelUpload(): void {
    this.uploaderComponent.cancelUpload();
  }
}

Image Preview & Thumbnail Generation

Image Upload with Preview

Add Image

export class ImageUploaderComponent {
  selectedImages: FileWithPreview[] = [];

  imageConfig: UploadConfig = {
    acceptedTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
    maxFileSize: 5 * 1024 * 1024,
    generateThumbnails: true,
    thumbnailSize: { width: 200, height: 200 },
    compressionQuality: 0.8
  };

  onImagesSelected(files: FileUploadMetadata[]): void {
    files.forEach(fileData => {
      if (fileData.file.type.startsWith('image/')) {
        this.generatePreview(fileData);
      }
    });
  }

  private generatePreview(fileData: FileUploadMetadata): void {
    const reader = new FileReader();
    reader.onload = (e) => {
      const preview: FileWithPreview = {
        ...fileData,
        preview: e.target?.result as string,
        thumbnail: this.generateThumbnail(e.target?.result as string)
      };
      this.selectedImages.push(preview);
    };
    reader.readAsDataURL(fileData.file);
  }

  private generateThumbnail(imageSrc: string): string {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    const img = new Image();
    
    img.onload = () => {
      canvas.width = 200;
      canvas.height = 200;
      ctx?.drawImage(img, 0, 0, 200, 200);
    };
    
    img.src = imageSrc;
    return canvas.toDataURL('image/jpeg', 0.8);
  }

  removeImage(index: number): void {
    this.selectedImages.splice(index, 1);
  }
}

interface FileWithPreview extends FileUploadMetadata {
  preview: string;
  thumbnail: string;
}

📚 API Reference

Component Inputs

Property Type Default Description
multiple boolean false Allow multiple file selection
maxSize number -1 Maximum file size in bytes
acceptedTypes string[] [] Array of accepted file types
uploadUrl string '' Upload endpoint URL
autoUpload boolean true Automatically start upload on file selection

Component Events

Event Type Description
filesSelected FileUploadMetadata[] Emitted when files are selected
uploadProgress UploadProgressEvent Emitted during upload progress
uploadComplete any Emitted when upload completes successfully
uploadError any Emitted when upload fails