PHPackages                             thingmabobby/file-upload-service - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [File &amp; Storage](/categories/file-storage)
4. /
5. thingmabobby/file-upload-service

ActiveLibrary[File &amp; Storage](/categories/file-storage)

thingmabobby/file-upload-service
================================

A comprehensive PHP file upload service supporting base64 data URIs, traditional file uploads, HEIC/HEIF conversion, and multiple file types

v2.3.1(5mo ago)110UnlicensePHPPHP ^8.1

Since Oct 19Pushed 5mo agoCompare

[ Source](https://github.com/thingmabobby/FileUploadService)[ Packagist](https://packagist.org/packages/thingmabobby/file-upload-service)[ Docs](https://github.com/thingmabobby/file-upload-service)[ GitHub Sponsors](https://github.com/sponsors/thingmabobby)[ RSS](/packages/thingmabobby-file-upload-service/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (6)Dependencies (4)Versions (7)Used By (0)

FileUploadService
=================

[](#fileuploadservice)

A comprehensive PHP service for handling file uploads from base64 encoded data URIs or traditional file uploads ($\_FILES array). Supports images, PDFs, CAD drawings, videos, and other common file types with pluggable storage backends, advanced security features, and flexible validation options.

Features
--------

[](#features)

- **Multiple Input Types**: Handles both `$_FILES` arrays and base64 data URIs seamlessly
- **Comprehensive File Type Support**: Images, PDFs, CAD files, documents, archives, and videos
- **Custom MIME Type Support**: Allow specific MIME types and custom extensions beyond predefined categories
- **Advanced Security**: Path traversal protection, filename sanitization, MIME type validation, atomic file operations
- **HEIC/HEIF Conversion**: Automatically converts HEIC/HEIF files to JPEG with graceful degradation
- **Collision Resolution**: Multiple strategies for handling filename conflicts (increment, UUID, timestamp, custom)
- **Error Handling**: Comprehensive error tracking with rollback support
- **High Performance Mode**: Optimized for network storage and high-collision scenarios
- **Pluggable Storage**: Extensible storage backends via FileSaverInterface (filesystem, cloud, custom)
- **Type Safety**: Full enum-based type system for file types and strategies
- **Separate DTOs**: Specialized data transfer objects for different input types
- **Cross-Platform**: Full Windows, Linux, and macOS compatibility with proper path handling

Minimum Requirements
--------------------

[](#minimum-requirements)

- PHP 8.1 or higher

Suggested Requirements
----------------------

[](#suggested-requirements)

- `ext-fileinfo` for MIME type validation to work
- `maestroerror/php-heic-to-jpg` for HEIC/HEIF conversion

Installation
------------

[](#installation)

```
composer require thingmabobby/file-upload-service
```

Basic Usage
-----------

[](#basic-usage)

```
use FileUploadService\FileUploadService;

// Simple usage - FilesystemSaver auto-configured from uploadDestination
$service = new FileUploadService(['image', 'pdf']);

try {
    $result = $service->save(
        input: $_FILES['files'],
        uploadDestination: __DIR__ . '/uploads',  // Absolute path - basePath derived automatically!
        filenames: ['photo.jpg', 'document.pdf']
    );

    if ($result->hasSuccessfulUploads()) {
        echo "Uploaded " . $result->successfulCount . " files\n";
        foreach ($result->successfulFiles as $filePath) {
            echo "Saved: " . $filePath . "\n";
        }
    }

    if ($result->hasErrors()) {
        foreach ($result->getErrorMessages() as $errorMessage) {
            echo "Error: " . $errorMessage . "\n";
        }
    }
} catch (RuntimeException $e) {
    echo "Critical error: " . $e->getMessage() . "\n";
}
```

### Traditional Usage (Backward Compatible)

[](#traditional-usage-backward-compatible)

```
use FileUploadService\FileUploadService;
use FileUploadService\FilesystemSaver;

// Configure FilesystemSaver explicitly
$fileSaver = new FilesystemSaver('/var/www/uploads', 0755, true);
$service = new FileUploadService(['image', 'pdf'], $fileSaver);

$result = $service->save(
    input: $_FILES['files'],
    uploadDestination: 'photos',  // Relative to basePath
    filenames: ['photo1.jpg', 'photo2.jpg']
);
```

Custom MIME Type Support
------------------------

[](#custom-mime-type-support)

The service now supports custom MIME types and extensions beyond the predefined categories:

### Using Constructor with MIME Types

[](#using-constructor-with-mime-types)

```
// Allow specific MIME types using 'mime:' prefix
$service = new FileUploadService([
    'image',                    // All image types
    'mime:text/csv',           // Custom CSV MIME type
    'mime:application/x-custom', // Custom application MIME type
    '.xyz'                     // Custom extension
]);
```

### Using Setter Methods

[](#using-setter-methods)

```
$service = new FileUploadService(['image']);

// Set allowed categories
$service->setAllowedCategories(['image', 'video']);

// Set custom extensions
$service->setAllowedExtensions(['xyz', 'custom']);

// Set custom MIME types
$service->setAllowedMimeTypes(['text/csv', 'application/x-custom']);

// Get current settings
$categories = $service->getAllowedCategories(); // Returns array
$extensions = $service->getAllowedExtensions(); // Returns array
$mimeTypes = $service->getAllowedMimeTypes(); // Returns array
```

### Mixed Configuration Example

[](#mixed-configuration-example)

```
$service = new FileUploadService([
    'image',                    // Image category
    'video',                    // Video category
    'mime:text/csv',           // Custom CSV MIME type
    'mime:application/x-php',   // Custom PHP MIME type
    '.xyz',                    // Custom extension
    '.custom'                  // Another custom extension
]);

// Additional configuration via setters
$service->setAllowedMimeTypes(['text/plain', 'application/json']);
$service->setAllowedExtensions(['txt', 'json']);
```

Video File Support
------------------

[](#video-file-support)

The service now includes comprehensive video file support:

```
// Allow video files
$service = new FileUploadService(['image', 'video']);

// Supported video formats:
// MP4, AVI, MOV, WMV, FLV, WebM, MKV, MPEG, MPG, 3GP, M4V, OGV
```

Exception Handling
------------------

[](#exception-handling)

The `FileUploadService` uses a **two-tier exception handling strategy**:

### **Critical Errors (Thrown Exceptions)**

[](#critical-errors-thrown-exceptions)

These errors prevent the entire operation from proceeding and should be caught with try-catch:

- **Directory Issues**: Upload destination doesn't exist and can't be created
- **Permission Issues**: Upload destination is not writable
- **Parameter Mismatches**: Filename count doesn't match input count
- **Configuration Errors**: Invalid file types provided

### **Individual File Errors (Captured in Result)**

[](#individual-file-errors-captured-in-result)

These errors affect individual files but allow the operation to continue:

- **File Validation Failures**: Invalid file types, corrupted data
- **Upload Errors**: PHP upload errors (file too large, partial upload, etc.)
- **Processing Errors**: HEIC conversion failures, file saving issues

### **Best Practice**

[](#best-practice)

Always wrap the `save()` method in a try-catch block to handle critical errors, then check the result for individual file errors:

```
try {
    $result = $fileUploadService->save($input, $uploadDestination, $filenames);

    // Handle individual file results
    if ($result->hasSuccessfulUploads()) {
        // Process successful uploads
    }

    if ($result->hasErrors()) {
        // Handle individual file errors
    }
} catch (RuntimeException $e) {
    // Handle critical system errors
    error_log("File upload failed: " . $e->getMessage());
}
```

Configuration
-------------

[](#configuration)

### File Type Restrictions

[](#file-type-restrictions)

```
// Simple usage with raw strings (recommended)
$service = new FileUploadService([
    'image',
    'pdf',
    'video',
    'cad'
]);

// Allow all file types
$service = new FileUploadService(['all']);

// Mix categories, custom extensions, and MIME types
$service = new FileUploadService([
    'image',
    'video',
    'mime:text/csv',
    'mime:application/x-custom',
    '.xyz',
    '.custom'
]);

// Advanced usage with enums (optional)
use FileUploadService\Enum\FileTypeEnum;

$service = new FileUploadService([
    FileTypeEnum::IMAGE,
    FileTypeEnum::VIDEO,
    FileTypeEnum::PDF
]);

// Get all available file types - returns array of FileTypeEnum cases
$allFileTypes = FileUploadService::getAvailableFileTypeCategories();
```

### HEIC/HEIF Conversion

[](#heicheif-conversion)

The service automatically attempts to convert HEIC/HEIF files to JPEG format. If the conversion library is not available, it gracefully degrades by saving the original HEIC/HEIF file as-is.

```
// Enable HEIC to JPEG conversion (default)
$service = new FileUploadService(
    allowedFileTypes: ['image'],
    convertHeicToJpg: true
);

// Disable HEIC conversion (save as-is)
$service = new FileUploadService(
    allowedFileTypes: ['image'],
    convertHeicToJpg: false
);

// Check if HEIC conversion is available
if ($service->isHeicConversionEnabled()) {
    echo "HEIC conversion is enabled";
}
```

**HEIC Conversion Behavior:**

- **Default behavior**: HEIC/HEIF files are automatically detected via MIME type and converted to JPEG format
- **Detection method**: Uses MIME type from uploaded file (primary), finfo() detection (fallback), and binary header checks (last resort)
- **Extension-agnostic**: Files are detected by content, not file extension, preventing misidentification
- **Conversion fails**: Falls back to saving the original HEIC/HEIF file
- **Always graceful**: Never fails uploads due to conversion issues
- **Library dependency**: Uses `maestroerror/php-heic-to-jpg` package (required dependency)

### Collision Resolution Strategies

[](#collision-resolution-strategies)

```
// Increment strategy (default): filename_1.jpg, filename_2.jpg
$service = new FileUploadService(
    allowedFileTypes: ['image'],
    collisionStrategy: 'increment'
);

// UUID strategy: filename_a1b2c3d4.jpg
$service = new FileUploadService(
    allowedFileTypes: ['image'],
    collisionStrategy: 'uuid'
);

// Timestamp strategy: filename_1234567890.jpg
$service = new FileUploadService(
    allowedFileTypes: ['image'],
    collisionStrategy: 'timestamp'
);

// Advanced usage with enums (optional)
$service = new FileUploadService(
    allowedFileTypes: ['image'],
    collisionStrategy: CollisionStrategyEnum::UUID
);

// Custom strategy
$service = new FileUploadService(
    allowedFileTypes: ['image'],
    collisionStrategy: fn($base, $dir, $exts, $used) => $base . '_custom_' . bin2hex(random_bytes(4))
);
```

### High Performance Mode

[](#high-performance-mode)

```
// Optimized for network storage or high-collision scenarios
$service = new FileUploadService(
    allowedFileTypes: ['image'],
    highPerformanceMode: true
);
// Automatically uses 'uuid' strategy and filters extensions to reduce filesystem calls
```

### Error Handling and Rollback

[](#error-handling-and-rollback)

```
// Enable rollback on error (default: false)
// When enabled, removes all successfully uploaded files if any error occurs
$service = new FileUploadService(
    allowedFileTypes: ['image'],
    rollbackOnError: true
);

// Default behavior (rollback disabled)
$service = new FileUploadService(['image']); // rollbackOnError defaults to false

// Check if rollback is enabled
if ($service->isRollbackOnErrorEnabled()) {
    echo "Rollback is enabled";
}
```

### Storage Backends

[](#storage-backends)

```
use FileUploadService\FileUploadService;

// Simple approach: FilesystemSaver is auto-created from uploadDestination
$service = new FileUploadService(['image']);
$result = $service->save($_FILES['image'], '/var/www/uploads', ['photo.jpg']);
// Automatically creates FilesystemSaver with basePath derived from uploadDestination

// Advanced: Provide FilesystemSaver in constructor (backward compatible)
use FileUploadService\FilesystemSaver;
$filesystemSaver = new FilesystemSaver('/var/uploads', 0755, true);
$service = new FileUploadService(
    allowedFileTypes: ['image'],
    fileSaver: $filesystemSaver
);

// Advanced: Provide FileSaverInterface per save() call
$result = $service->save(
    input: $_FILES['image'],
    uploadDestination: 'uploads',
    filenames: ['photo.jpg'],
    fileSaver: $customFileSaver  // Optional override
);

// Cloud storage example (implement FileSaverInterface)
// $cloudSaver = new CloudStorageSaver('bucket-name', 'region', 'credentials');
// $service = new FileUploadService(['image']);
// $result = $service->save($input, 'uploads', $filenames, fileSaver: $cloudSaver);
```

Input Types
-----------

[](#input-types)

### $\_FILES Structure Handling

[](#_files-structure-handling)

The service automatically detects and handles different `$_FILES` array structures:

**Single File Upload:**

```
$_FILES['files'] = [
    'name' => 'image.jpg',           // String
    'type' => 'image/jpeg',          // String
    'tmp_name' => '/tmp/abc123',     // String
    'error' => 0,                    // Integer
    'size' => 12345                  // Integer
];
```

**Multiple File Upload:**

```
$_FILES['files'] = [
    'name' => ['image1.jpg', 'image2.png'],     // Array of strings
    'type' => ['image/jpeg', 'image/png'],      // Array of strings
    'tmp_name' => ['/tmp/abc123', '/tmp/def456'], // Array of strings
    'error' => [0, 0],                          // Array of integers
    'size' => [12345, 67890]                    // Array of integers
];
```

### Base64 Data URIs

[](#base64-data-uris)

```
$dataUri = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ...';
```

### Mixed Input Types

[](#mixed-input-types)

```
$input = [
    'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ...',  // base64
    $_FILES['uploaded_file'],                                // $_FILES
    'data:application/pdf;base64,JVBERi0xLjQKMSAwIG9i...', // base64
    $_FILES['another_file']                                  // $_FILES
];
$filenames = ['image1.jpg', 'upload1.pdf', 'document.pdf', 'file2.doc'];
$result = $fileUploadService->save($input, $uploadDestination, $filenames);
```

Supported File Types
--------------------

[](#supported-file-types)

The service supports a comprehensive range of file types through the `SupportedFileTypesEnum`. Here are all supported file types organized by category:

### Images

[](#images)

ExtensionMIME TypeDescription`jpg``image/jpeg`JPEG images`png``image/png`PNG images`gif``image/gif`GIF images`webp``image/webp`WebP images`avif``image/avif`AVIF images`jxl``image/jxl`JPEG XL images`bmp``image/bmp`BMP images`tiff``image/tiff`TIFF images`heic``image/heic`HEIC images (converted to JPEG)`heif``image/heif`HEIF images (converted to JPEG)### Videos

[](#videos)

ExtensionMIME TypeDescription`mp4``video/mp4`MP4 videos`avi``video/x-msvideo`AVI videos`mov``video/quicktime`QuickTime videos`wmv``video/x-ms-wmv`Windows Media videos`flv``video/x-flv`Flash videos`webm``video/webm`WebM videos`mkv``video/x-matroska`Matroska videos`mpeg``video/mpeg`MPEG videos`mpg``video/mpeg`MPEG videos`3gp``video/3gpp`3GPP videos`m4v``video/x-m4v`iTunes videos`ogv``video/ogg`Ogg videos### PDF Documents

[](#pdf-documents)

ExtensionMIME TypeDescription`pdf``application/pdf`Standard PDF documents`pdf``application/x-pdf`Alternative PDF MIME type`pdf``application/acrobat`Adobe Acrobat PDF`pdf``application/vnd.pdf`Vendor-specific PDF### Documents

[](#documents)

ExtensionMIME TypeDescription`doc``application/msword`Microsoft Word documents`docx``application/vnd.openxmlformats-officedocument.wordprocessingml.document`Microsoft Word XML documents`xls``application/vnd.ms-excel`Microsoft Excel spreadsheets`xlsx``application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`Microsoft Excel XML spreadsheets`ppt``application/vnd.ms-powerpoint`Microsoft PowerPoint presentations`pptx``application/vnd.openxmlformats-officedocument.presentationml.presentation`Microsoft PowerPoint XML presentations`txt``text/plain`Plain text files`rtf``application/rtf`Rich Text Format documents`csv``text/csv`Comma-separated values`xml``application/xml`XML documents`json``application/json`JSON documents`odt``application/vnd.oasis.opendocument.text`OpenDocument text`ods``application/vnd.oasis.opendocument.spreadsheet`OpenDocument spreadsheet`odp``application/vnd.oasis.opendocument.presentation`OpenDocument presentation### CAD Files

[](#cad-files)

ExtensionMIME TypeDescription`dwg``application/dwg`AutoCAD drawings`dxf``application/dxf`AutoCAD DXF files`step``application/step`STEP 3D models`iges``application/iges`IGES 3D models`stl``application/stl`STL 3D models`sldprt``application/sldprt`SolidWorks part files`sldasm``application/sldasm`SolidWorks assembly files### Archives

[](#archives)

ExtensionMIME TypeDescription`zip``application/zip`ZIP archives`rar``application/x-rar-compressed`RAR archives`7z``application/x-7z-compressed`7-Zip archives`tar``application/x-tar`TAR archives`gz``application/gzip`GZIP compressed files### File Type Categories

[](#file-type-categories)

The service organizes file types into the following categories (accessible via `FileTypeEnum`):

- **`image`** - All image formats (JPEG, PNG, GIF, WebP, AVIF, JXL, BMP, TIFF, HEIC, HEIF)
- **`video`** - All video formats (MP4, AVI, MOV, WMV, FLV, WebM, MKV, MPEG, 3GP, M4V, OGV)
- **`pdf`** - PDF documents (all MIME variants)
- **`doc`** - All document formats (Office, OpenDocument, text files)
- **`cad`** - CAD and technical drawing files
- **`archive`** - Compressed archive formats
- **`all`** - Allow all file types (no restrictions)

**Note:** For programmatic access to this information, use the `SupportedFileTypesEnum` class which provides methods to get extensions, MIME types, and categories for each supported file type.

Security Features
-----------------

[](#security-features)

### Path Traversal Protection

[](#path-traversal-protection)

- `FilesystemSaver::resolvePath()` prevents `../` attacks in filenames
- Upload destinations can use legitimate directory navigation (e.g., `../images/`)
- All paths are validated to stay within `basePath`
- Absolute paths are rejected for security

### Filename Sanitization

[](#filename-sanitization)

- `FilenameSanitizer::cleanFilename()` removes dangerous characters
- Null byte removal prevents security bypasses
- Unicode normalization prevents confusion attacks
- Length limits prevent filesystem issues

### MIME Type Validation

[](#mime-type-validation)

- `FileServiceValidator::isFileTypeAllowed()` validates actual file content
- Uses `finfo_open()` to detect real MIME types
- Prevents file type spoofing attacks
- Custom MIME types are validated against actual file content

### Atomic File Operations

[](#atomic-file-operations)

- All file saves use temporary files + `rename()` for atomicity
- Prevents race conditions and partial file writes
- Secure temporary directory creation with restricted permissions

### Double Extension Protection

[](#double-extension-protection)

- Files like `malware.php.txt` are treated as `.txt` files (safe)
- Files like `malware.txt.php` are blocked by MIME validation
- MIME type detection prevents execution of disguised files

API Reference
-------------

[](#api-reference)

### FileUploadService

[](#fileuploadservice-1)

#### Constructor

[](#constructor)

```
public function __construct(
    private readonly array $allowedFileTypes = [FileTypeEnum::IMAGE, FileTypeEnum::PDF, FileTypeEnum::CAD],
    private readonly ?FileSaverInterface $fileSaver = null,
    private readonly bool $createDirectory = true,
    private readonly int $directoryPermissions = 0775,
    private readonly bool $rollbackOnError = false,
    string|callable|CollisionStrategyEnum $collisionStrategy = CollisionStrategyEnum::INCREMENT,
    private readonly bool $highPerformanceMode = false,
    private readonly bool $convertHeicToJpg = true
)
```

#### Public Methods

[](#public-methods)

**File Management:**

- `save(array $inputs, string $uploadDestination, array $filenames, bool $overwriteExisting = false, bool $generateUniqueFilenames = false, ?FileSaverInterface $fileSaver = null): FileUploadResult`

**Configuration:**

- `setAllowedFileTypes(array $allowedFileTypes): void`
- `getAllowedFileTypes(): array`
- `setAllowedCategories(array $categories): void`
- `getAllowedCategories(): array`
- `setAllowedExtensions(array $extensions): void`
- `getAllowedExtensions(): array`
- `setAllowedMimeTypes(array $mimeTypes): void`
- `getAllowedMimeTypes(): array`
- `allowFileType(string|array $fileTypes): void`
- `disallowFileType(string|array $fileTypes): void`

**Status Checks:**

- `isRollbackOnErrorEnabled(): bool`
- `isHeicConversionEnabled(): bool`
- `isFileTypeCategoryAllowed(string $fileType): bool`
- `isFileTypeAllowedByExtension(string $extension): bool`
- `isUnrestricted(): bool`

**Utilities:**

- `getFileTypeCategoryFromExtension(string $extension): FileTypeEnum|string`
- `getRestrictionDescription(): string`
- `cleanFilename(string $filename, bool $removeUnderscores = false): string`

#### Static Methods

[](#static-methods)

- `getAvailableFileTypeCategories(): array`

### FileUploadResult

[](#fileuploadresult)

**Properties:**

- `public readonly array $successfulFiles` - Array of successfully uploaded file paths
- `public readonly array $errors` - Array of upload errors
- `public readonly int $totalFiles` - Total number of files attempted
- `public readonly int $successfulCount` - Number of successfully uploaded files

**Methods:**

- `hasErrors(): bool`
- `isCompleteSuccess(): bool`
- `hasSuccessfulUploads(): bool`
- `getErrorMessages(): array`
- `getErrorForFile(string $filename): ?FileUploadError`

### FileUploadError

[](#fileuploaderror)

**Properties:**

- `public readonly string $filename` - The filename that caused the error
- `public readonly string $message` - The error message
- `public readonly string $code` - The error code (optional, defaults to empty string)

**Methods:**

- `getDescription(): string`

Architecture
------------

[](#architecture)

The service is built with a clean separation of concerns:

- **FileUploadService**: Main orchestrator and public API
- **FileServiceValidator**: Handles file validation and type checking
- **FileCollisionResolver**: Manages filename collision resolution
- **FileUploadSave**: Handles actual file processing and saving operations
- **FileSaverInterface**: Pluggable storage backend interface
- **FilesystemSaver**: Default filesystem storage implementation
- **CloudStorageSaver**: Example cloud storage implementation
- **Enum Classes**: Type-safe constants and enumerations (FileTypeEnum, CollisionStrategyEnum, UploadErrorCodeEnum, SupportedFileTypesEnum)
- **DTO Classes**: Specialized data transfer objects (FileUploadDTO, DataUriDTO)
- **Utils**: Utility classes (FilenameSanitizer)

### Storage Backend Interface

[](#storage-backend-interface)

The service uses the `FileSaverInterface` to abstract file storage operations, allowing for different storage backends:

- **FilesystemSaver**: Local filesystem storage (included)
- **Cloud Storage**: AWS S3, Google Cloud Storage, Azure Blob Storage (implementations can be added)
- **Custom Storage**: Any storage system can be implemented by implementing `FileSaverInterface`

The interface provides methods for:

- `saveFile(string $source, string $targetPath, bool $overwriteExisting = false): string`
- `resolveTargetPath(string $uploadDestination, string $filename): string`
- `ensureUploadDestinationExists(string $uploadDestination): void`
- `fileExists(string $targetPath): bool`
- `deleteFile(string $targetPath): bool`
- `getBasePath(): string`

Testing
-------

[](#testing)

The package includes comprehensive test coverage with PHPUnit:

```
# Run all tests
composer test

# Run tests with HTML coverage report
composer test-coverage

# Run tests with text coverage report
composer test-coverage-text

# Run tests with verbose output
composer test-verbose

# Run tests and stop on first failure
composer test-stop-on-failure
```

License
-------

[](#license)

Unlicense - See LICENSE file for details.

###  Health Score

35

—

LowBetter than 79% of packages

Maintenance70

Regular maintenance activity

Popularity7

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~6 days

Total

6

Last Release

172d ago

Major Versions

v1.0 → v2.02025-10-20

### Community

Maintainers

![](https://www.gravatar.com/avatar/4fee267f907de08e3fdd0d07da9031b002a6657a4746a40794db27a06fb7c6e7?d=identicon)[thingmabobby](/maintainers/thingmabobby)

---

Top Contributors

[![thingmabobby](https://avatars.githubusercontent.com/u/166399989?v=4)](https://github.com/thingmabobby "thingmabobby (16 commits)")

---

Tags

phppdfbase64imagesjpeguploadfile-uploaddocumentsfile managementcadheic

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/thingmabobby-file-upload-service/health.svg)

```
[![Health](https://phpackages.com/badges/thingmabobby-file-upload-service/health.svg)](https://phpackages.com/packages/thingmabobby-file-upload-service)
```

###  Alternatives

[blueimp/jquery-file-upload

File Upload widget for jQuery.

141.5M18](/packages/blueimp-jquery-file-upload)[enyo/dropzone

Handles drag and drop of files for you.

101.9M31](/packages/enyo-dropzone)[christianbarkowsky/contao-tiny-compress-images

This plugin automatically optimizes your images (JPG, PNG, WebP) by integrating with the popular image compression services TinyJPG and TinyPNG.

2719.0k](/packages/christianbarkowsky-contao-tiny-compress-images)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
