Enhanced File Management Guide
Last Updated: 2026-01-12 Status: Implemented Plan Reference: 030-enhanced-file-management.md, 057-enhanced-file-management-enhancement.md, 092-enhanced-file-management-improvement.md
Overview
Enhanced File Management extends the basic file sharing system with advanced features including virus scanning, file versioning, bulk operations, file categories, and improved search capabilities. These features provide enterprise-grade file management for the client portal.
Plan 057 Enhancements (2026-01-10):
- Enhanced virus scanning UI with clear status indicators
- Rich file preview system (8+ file types)
- Batch upload with progress tracking
- Advanced file search and filtering
- Improved file versioning interface
- Real-time scan status updates
Plan 092 Enhancements (2026-01-12):
- Centralized configuration (
config/file-management.php) - File tagging component with Alpine.js interactivity
- FileBatchController for comprehensive batch operations
- StorageAnalyticsService for storage insights
- Batch routes for download, delete, move, tag, visibility, rescan
Table of Contents
- Accessing Features
- Features
- How to Use
- Virus Scanning
- File Versioning
- Batch Uploads
- File Preview
- Advanced Search
- Bulk Operations
- Technical Architecture
- Related Features
Accessing Features
Navigation
| Access Point | Location | URL | Role |
|---|---|---|---|
| Project Files | Project detail | /admin/projects/{id} (files section) | Admin |
| File Detail | File row | /admin/files/{id} | Admin |
| File Versions | File detail modal | /admin/files/{id}/versions | Admin |
| Bulk Actions | File list | Checkbox selection on project page | Admin |
Note: Files are accessed within their project context. There is no standalone file browser - files are managed per-project.
Permissions
| Action | Admin | Client User |
|---|---|---|
| View file versions | ✅ | ❌ |
| Restore versions | ✅ | ❌ |
| Bulk operations | ✅ | ❌ |
| Categorize files | ✅ | ❌ |
| View scan status | ✅ | ❌ |
Features
Virus Scanning
- Automatic scan on upload
- ClamAV integration
- Quarantine infected files
- Scan status indicators
File Versioning
- Automatic version creation on re-upload
- Version history with timestamps
- Restore previous versions
- Compare versions
Bulk Operations
- Multi-select files
- Bulk delete
- Bulk move between projects
- Bulk visibility change
- Bulk download (ZIP)
File Categories
- Predefined categories
- Custom category creation
- Category-based filtering
- Color-coded labels
File Search
- Search by filename
- Filter by type, date, category
- Full-text content search (PDF/documents)
File Preview
- Image preview in modal
- PDF preview
- Video preview
- Audio preview
Batch Uploads
Overview
The batch upload system provides a queue-based upload experience with progress tracking, concurrent uploads, and error handling.
Features
| Feature | Description |
|---|---|
| Drag & Drop | Drop multiple files onto the upload zone |
| Queue Management | Track all pending, uploading, and completed files |
| Concurrent Uploads | Up to 3 simultaneous uploads |
| Progress Tracking | Real-time progress bars per file |
| Retry Failed | One-click retry for failed uploads |
| Cancel Uploads | Cancel queued or in-progress uploads |
Using Batch Upload
- Navigate to project files
- Drag files onto the drop zone (or click browse)
- Files appear in the upload queue with status
- Progress bars show upload completion
- Completed files show green checkmark
- Failed files show Retry button
Upload Queue States
| State | Icon | Description |
|---|---|---|
| Queued | ⏳ | Waiting to start |
| Uploading | ⬆️ | Currently uploading (shows progress) |
| Completed | ✅ | Successfully uploaded |
| Failed | ❌ | Upload failed (can retry) |
Configuration
// Maximum concurrent uploads
maxConcurrent: 3
// Maximum file size (100MB)
maxFileSize: 100 * 1024 * 1024
// Allowed file types
allowedTypes: ['image/*', 'application/pdf', 'video/*', ...]
File Preview
Supported File Types
The enhanced preview system supports 8+ file types with rich viewing capabilities:
| Type | Extensions | Preview Features |
|---|---|---|
| Image | jpg, png, gif, webp, svg | Zoom, rotate, pan |
| Embedded viewer | ||
| Video | mp4, webm, mov | Native video player with controls |
| Audio | mp3, wav, ogg | Audio player with waveform |
| Code | php, js, ts, py, css, html, json | Syntax highlighting |
| Spreadsheet | csv, xlsx, xls | Table preview (first 100 rows) |
| Text | txt, md, log | Plain text viewer |
| Document | doc, docx | Download prompt (preview not available) |
File Icons
Files display type-specific icons based on extension:
| Icon | File Types |
|---|---|
document-text | pdf, doc, docx |
photo | jpg, png, gif, webp |
film | mp4, webm, mov |
musical-note | mp3, wav, ogg |
code-bracket | php, js, py, css, html |
table-cells | csv, xlsx, xls |
document | txt, md, log |
Preview Modal Features
- Navigation: Previous/Next buttons for multiple files
- Actions: Download, share, and close buttons
- Keyboard: Escape to close, arrow keys to navigate
- Responsive: Full-screen on mobile devices
Using File Preview
- Click on any file in the file list
- Preview modal opens with appropriate viewer
- Use controls based on file type:
- Images: Zoom (+/-), rotate, fit to window
- Videos: Play, pause, seek, volume, fullscreen
- Audio: Play, pause, seek, volume
- Code: Scroll with syntax highlighting
- Navigate between files with arrow buttons
- Click Download to save file
- Click X or press Escape to close
Advanced Search
Search Capabilities
The FileSearchService provides comprehensive file filtering:
| Filter | Options | Description |
|---|---|---|
| Text Search | Any text | Search filename, description, tags |
| File Type | images, documents, videos, audio, archives, code | Filter by category |
| Date Range | today, yesterday, this_week, this_month, etc. | Filter by upload date |
| Size Range | small, medium, large, xlarge | Filter by file size |
| Scan Status | clean, pending, infected, error | Filter by virus scan status |
| Visibility | public, private | Filter by client visibility |
| Project | Project ID | Filter by specific project |
| Uploader | User ID | Filter by who uploaded |
| Tags | Tag names | Filter by assigned tags |
Date Presets
| Preset | Description |
|---|---|
| today | Uploaded today |
| yesterday | Uploaded yesterday |
| this_week | Uploaded this week |
| last_week | Uploaded last week |
| this_month | Uploaded this month |
| last_month | Uploaded last month |
| this_year | Uploaded this year |
Size Ranges
| Range | Size |
|---|---|
| small | Under 1 MB |
| medium | 1 MB - 10 MB |
| large | 10 MB - 100 MB |
| xlarge | Over 100 MB |
Using Advanced Search
- Navigate to Admin → Files
- Use the search box for text search
- Click filter dropdowns to narrow results:
- Type: Select file category
- Date: Choose date preset or custom range
- Size: Select size range
- Status: Filter by scan status
- Active filters appear as removable chips
- Click Clear all to reset filters
- Results update in real-time
Search API Usage
use App\Services\Files\FileSearchService;
$service = app(FileSearchService::class);
$results = $service->search([
'query' => 'invoice',
'types' => 'documents',
'date_preset' => 'this_month',
'size_range' => 'small',
'scan_status' => 'clean',
]);
// Get available filter options
$fileTypes = $service->getAvailableFileTypes();
$sizeRanges = $service->getAvailableSizeRanges();
$datePresets = $service->getAvailableDatePresets();
How to Use
Viewing File Versions
- Navigate to project files
- Click on a file row to open detail modal
- Click "Version History" tab
- View all previous versions with:
- Version number
- Upload date
- Uploader name
- File size
Restoring a Previous Version
- Open file version history
- Find desired version
- Click "Restore" button
- Confirm restoration
- Current file becomes new version
- Selected version becomes current
Uploading a New Version
- Navigate to project files
- Find existing file
- Click "Upload New Version"
- Select new file
- Previous file saved as version
- New file becomes current
Using Bulk Operations
- Navigate to file list
- Check boxes next to files
- Select action from toolbar:
- Delete Selected: Remove all selected files
- Change Visibility: Toggle client visibility
- Move To: Move to different project
- Download ZIP: Download all as archive
- Confirm action
Categorizing Files
- Navigate to project files
- Click file to open modal
- Click "Category" dropdown
- Select category:
- Contracts
- Deliverables
- Reference
- Drafts
- Final
- Custom...
- Category label appears on file
Searching Files
- Navigate to Admin → Files
- Use search box for filename
- Use filters sidebar:
- File type (Images, Documents, etc.)
- Date range
- Category
- Project
- Uploader
- Results update dynamically
Virus Scanning
How It Works
- File uploaded to temporary storage
- ClamAV daemon scans file
- Clean files moved to permanent storage
- Infected files quarantined
- User notified of scan result
Scan Statuses
| Status | Icon | Description |
|---|---|---|
| Pending | ⏳ | Awaiting scan |
| Clean | ✅ | No threats found |
| Infected | ❌ | Threat detected |
| Error | ⚠️ | Scan failed |
Configuration
# .env
CLAMAV_ENABLED=true
CLAMAV_SOCKET=/var/run/clamav/clamd.ctl
QUARANTINE_PATH=storage/app/quarantine
Viewing Quarantined Files
- Navigate to Admin → Files → Quarantined
- View list of infected files
- Options:
- Delete permanently
- Whitelist (if false positive)
- View scan details
File Versioning
Version Creation
Versions are created when:
- Same filename uploaded to same project
- "Upload New Version" used
- File restored from version
Version Retention
| Setting | Default | Description |
|---|---|---|
| Max versions | 10 | Per file |
| Retention period | 90 days | Before cleanup |
| Include in backup | Yes | All versions |
Version Storage
// Version stored at
storage/app/project_files/versions/{file_id}/{version}.{ext}
Bulk Operations
Available Operations
| Operation | Description |
|---|---|
| Delete | Remove selected files permanently |
| Make Visible | Set client visibility to true |
| Make Hidden | Set client visibility to false |
| Move | Move to different project |
| Download | Package as ZIP and download |
| Categorize | Apply category to all |
Bulk Download
- Select files (max 100)
- Click "Download as ZIP"
- ZIP generated in background
- Download link provided
- ZIP available for 1 hour
Technical Architecture
Models
FileVersion Model: app/Models/FileVersion.php
class FileVersion extends Model
{
protected $fillable = [
'project_file_id',
'version_number',
'filename',
'path',
'size',
'uploaded_by',
];
}
FileCategory Model: app/Models/FileCategory.php
class FileCategory extends Model
{
protected $fillable = [
'name',
'color',
'icon',
'is_system',
];
}
Updated ProjectFile Model
// Additional fields
protected $fillable = [
// ... existing fields
'category_id',
'scan_status',
'scanned_at',
'threat_name',
'content_hash',
];
protected $casts = [
// ... existing casts
'scanned_at' => 'datetime',
];
// Relationships
public function versions(): HasMany
{
return $this->hasMany(FileVersion::class)->orderByDesc('version_number');
}
public function category(): BelongsTo
{
return $this->belongsTo(FileCategory::class);
}
Services
FileVersionService: app/Services/FileVersionService.php
- Creates new versions
- Restores versions
- Cleans old versions
VirusScanService: app/Services/VirusScanService.php
- Scans uploaded files
- Quarantines threats
- Reports results
BulkFileService: app/Services/BulkFileService.php
- Processes bulk operations
- Generates ZIP archives
Routes
// Version routes
Route::get('files/{file}/versions', [FileVersionController::class, 'index']);
Route::post('files/{file}/versions', [FileVersionController::class, 'store']);
Route::post('files/{file}/versions/{version}/restore', [FileVersionController::class, 'restore']);
Route::delete('files/{file}/versions/{version}', [FileVersionController::class, 'destroy']);
// Bulk routes (legacy)
Route::post('files/bulk/delete', [BulkFileController::class, 'delete']);
Route::post('files/bulk/visibility', [BulkFileController::class, 'visibility']);
Route::post('files/bulk/move', [BulkFileController::class, 'move']);
Route::post('files/bulk/download', [BulkFileController::class, 'download']);
Route::post('files/bulk/categorize', [BulkFileController::class, 'categorize']);
// Batch routes (new - Plan 092)
Route::prefix('files/batch')->name('files.batch.')->group(function () {
Route::post('download', [FileBatchController::class, 'download'])->name('download');
Route::post('delete', [FileBatchController::class, 'delete'])->name('delete');
Route::post('move', [FileBatchController::class, 'move'])->name('move');
Route::post('tag', [FileBatchController::class, 'tag'])->name('tag');
Route::post('untag', [FileBatchController::class, 'untag'])->name('untag');
Route::post('visibility', [FileBatchController::class, 'visibility'])->name('visibility');
Route::post('rescan', [FileBatchController::class, 'rescan'])->name('rescan');
});
// Scan routes
Route::get('files/{file}/scan-status', [FileScanController::class, 'status']);
Route::post('files/{file}/rescan', [FileScanController::class, 'rescan']);
Storage Analytics
The StorageAnalyticsService provides comprehensive storage insights:
use App\Services\StorageAnalyticsService;
$analytics = app(StorageAnalyticsService::class);
// Get overall storage overview
$overview = $analytics->getOverview();
// Returns: total_size, total_files, average_file_size, total_versions
// Get storage by client
$byClient = $analytics->getByClient(10); // Top 10 clients
// Returns: name, size, files, projects for each client
// Get storage by file type
$byType = $analytics->getByType();
// Returns: type, mime_category, size, count, icon
// Get storage growth trend
$trend = $analytics->getGrowthTrend(6); // Last 6 months
// Returns: month, size, count, cumulative_size
// Get storage by project
$byProject = $analytics->getByProject(10);
// Get scan statistics
$scanStats = $analytics->getScanStats();
// Returns: total_scanned, clean, infected, pending, clean_percentage
// Clear analytics cache
$analytics->clearCache();
Database Tables
Table: file_versions
| Column | Type | Description |
|---|---|---|
id | bigint | Primary key |
project_file_id | bigint | Parent file |
version_number | integer | Version (1, 2, 3...) |
filename | string | Version filename |
path | string | Storage path |
size | bigint | File size |
uploaded_by | bigint | User who uploaded |
created_at | timestamp | Version date |
Table: file_categories
| Column | Type | Description |
|---|---|---|
id | bigint | Primary key |
name | string | Category name |
color | string | Hex color code |
icon | string | Icon name |
is_system | boolean | System category |
Jobs
ScanFileJob: Queued virus scan
ScanFileJob::dispatch($file);
GenerateZipJob: Queued ZIP creation
GenerateZipJob::dispatch($files, $user);
Configuration
Central Configuration File
All file management settings are centralized in config/file-management.php:
// config/file-management.php
return [
'tagging' => [
'enabled' => env('FILE_TAGGING_ENABLED', true),
'max_tags_per_file' => env('FILE_MAX_TAGS', 10),
'default_colors' => ['#3B82F6', '#10B981', '#F59E0B', ...],
],
'batch' => [
'enabled' => env('FILE_BATCH_ENABLED', true),
'max_files' => env('FILE_BATCH_MAX_FILES', 100),
'max_download_size' => env('FILE_BATCH_MAX_DOWNLOAD_SIZE', 524288000), // 500MB
'operations' => [
'download' => true,
'delete' => true,
'move' => true,
'tag' => true,
'visibility' => true,
'rescan' => true,
],
],
'analytics' => [
'enabled' => env('STORAGE_ANALYTICS_ENABLED', true),
'cache_ttl' => env('STORAGE_ANALYTICS_CACHE_TTL', 900), // 15 minutes
],
'quotas' => [
'enabled' => env('STORAGE_QUOTAS_ENABLED', false),
'default_client_quota' => env('STORAGE_DEFAULT_CLIENT_QUOTA', 5368709120), // 5GB
],
'scanning' => [
'show_status_badge' => env('FILE_SHOW_SCAN_STATUS', true),
'block_infected_downloads' => env('FILE_BLOCK_INFECTED', true),
],
'preview' => [
'enabled' => env('FILE_PREVIEW_ENABLED', true),
'max_size' => env('FILE_PREVIEW_MAX_SIZE', 52428800), // 50MB
],
];
File Categories
Default categories are seeded:
// database/seeders/FileCategorySeeder.php
$categories = [
['name' => 'Contracts', 'color' => '#3B82F6', 'icon' => 'document-text'],
['name' => 'Deliverables', 'color' => '#10B981', 'icon' => 'check-circle'],
['name' => 'Reference', 'color' => '#6366F1', 'icon' => 'book-open'],
['name' => 'Drafts', 'color' => '#F59E0B', 'icon' => 'pencil'],
['name' => 'Final', 'color' => '#059669', 'icon' => 'badge-check'],
];
Related Features
Dependencies
| Feature | Relationship |
|---|---|
| File Sharing | Base file system |
| Background Jobs | Async scanning and ZIP |
Complementary Features
| Feature | Description |
|---|---|
| Activity Logging | Logs all file operations |
| Notifications | Scan result notifications |
| Admin Tools | File management utilities |
Best Practices
For Administrators
- Enable virus scanning in production
- Review quarantined files regularly
- Set version limits to manage storage
- Use categories for organization
- Run bulk cleanup periodically
For Developers
- Queue virus scans for performance
- Use transactions for bulk operations
- Clean up versions with scheduled job
- Index file content for search
Troubleshooting
| Issue | Solution |
|---|---|
| Scan stuck on pending | Check ClamAV daemon running |
| Version not creating | Check max version limit |
| Bulk download fails | Check file count limit (100) |
| Category not saving | Verify category exists |
ClamAV Issues
# Check ClamAV status
sudo systemctl status clamav-daemon
# Test scan manually
clamscan /path/to/file
# Update virus definitions
sudo freshclam
See Also
- File Sharing - Basic file operations
- Background Jobs - Async processing
- Activity Logging - Audit trail