media_picker_guard 0.0.1-beta.1
media_picker_guard: ^0.0.1-beta.1 copied to clipboard
Validates media file size, duration, and format before upload with friendly error messages. Prevents server rejections and improves user experience.
Media Picker Guard ๐ก๏ธ #
A comprehensive Flutter package that validates media files (images, videos, audio, documents) before upload with user-friendly error messages. Prevent server rejections and improve user experience by catching validation issues early.
๐ Features #
- ๐ Size Validation: Set minimum and maximum file size limits with friendly error messages
- โฑ๏ธ Duration Validation: Validate video and audio duration constraints
- ๐ฏ Format Validation: Restrict file extensions and MIME types
- ๐ Performance Optimized: Quick validation checks and batch processing
- ๐ฌ User-Friendly Errors: Customizable, localized error messages
- ๐ง Flexible Configuration: Pre-built configs for common scenarios + custom options
- ๐ฑ Cross-Platform: Works on iOS, Android, Web, and Desktop
- ๐งช Well Tested: Comprehensive test coverage
- ๐ Type Safe: Full TypeScript-like safety with Dart
๐ Getting Started #
Add to your pubspec.yaml:
dependencies:
media_picker_guard: ^0.0.1
Then run:
flutter pub get
๐ Usage #
Quick Start #
import 'package:media_picker_guard/media_picker_guard.dart';
import 'dart:io';
// Validate an image file
final config = MediaPickerGuard.imageUploadConfig(
maxSizeMB: 5,
allowedExtensions: ['jpg', 'jpeg', 'png'],
);
final file = File('/path/to/image.jpg');
final result = await MediaPickerGuard.validateFile(file, config: config);
if (result.isValid) {
print('โ
File is ready for upload!');
} else {
print('โ Validation failed: ${result.firstFriendlyErrorMessage}');
}
Pre-built Configurations #
Image Upload
final config = MediaPickerGuard.imageUploadConfig(
maxSizeMB: 5, // Maximum 5MB
allowedExtensions: ['jpg', 'png', 'gif'],
customErrorMessages: {
'fileSizeExceeded': 'Image too large! Max 5MB allowed.',
'formatNotAllowed': 'Only JPG, PNG, and GIF images are supported.',
},
);
Video Upload
final config = MediaPickerGuard.videoUploadConfig(
maxSizeMB: 100, // Maximum 100MB
maxDurationMinutes: 10, // Maximum 10 minutes
allowedExtensions: ['mp4', 'mov'],
customErrorMessages: {
'durationExceeded': 'Video too long! Maximum 10 minutes allowed.',
},
);
Audio Upload
final config = MediaPickerGuard.audioUploadConfig(
maxSizeMB: 20, // Maximum 20MB
maxDurationMinutes: 30, // Maximum 30 minutes
allowedExtensions: ['mp3', 'wav', 'aac'],
);
Document Upload
final config = MediaPickerGuard.documentUploadConfig(
maxSizeMB: 10, // Maximum 10MB
allowedExtensions: ['pdf', 'doc', 'docx'],
);
Custom Configuration #
final config = MediaValidationConfig(
maxSizeBytes: 5 * 1024 * 1024, // 5MB
minSizeBytes: 1024, // 1KB minimum
maxDuration: Duration(minutes: 5),
allowedExtensions: ['jpg', 'png', 'mp4'],
allowedMimeTypes: ['image/jpeg', 'image/png', 'video/mp4'],
validateFileAccess: true,
validateFileIntegrity: true,
customErrorMessages: {
'fileSizeExceeded': 'File is too large!',
'formatNotAllowed': 'File format not supported!',
},
);
Multiple File Validation #
final files = [
File('/path/to/image1.jpg'),
File('/path/to/image2.png'),
File('/path/to/video.mp4'),
];
final results = await MediaPickerGuard.validateFiles(files, config: config);
for (final entry in results.entries) {
final filePath = entry.key;
final result = entry.value;
if (result.isValid) {
print('โ
$filePath is valid');
} else {
print('โ $filePath: ${result.firstFriendlyErrorMessage}');
}
}
Quick Validation (Performance Optimized) #
// For performance-critical scenarios
final isValid = await MediaPickerGuard.isFileValid(file, config: config);
if (isValid) {
// Proceed with upload
} else {
// Get detailed errors only if needed
final result = await MediaPickerGuard.validateFile(file, config: config);
showErrorToUser(result.firstFriendlyErrorMessage);
}
File Information #
final fileInfo = await MediaPickerGuard.getFileInfo(file);
if (fileInfo != null) {
print('File: ${fileInfo['fileName']}');
print('Size: ${fileInfo['fileSizeFormatted']}');
print('Type: ${fileInfo['mimeType']}');
print('Is Image: ${fileInfo['isImage']}');
}
๐ฏ Common Use Cases #
1. Profile Picture Upload #
final config = MediaPickerGuard.imageUploadConfig(
maxSizeMB: 2,
allowedExtensions: ['jpg', 'jpeg', 'png'],
customErrorMessages: {
'fileSizeExceeded': 'Profile picture must be under 2MB',
'formatNotAllowed': 'Please select a JPG or PNG image',
},
);
2. Social Media Video Upload #
final config = MediaPickerGuard.videoUploadConfig(
maxSizeMB: 50,
maxDurationMinutes: 5,
allowedExtensions: ['mp4', 'mov'],
customErrorMessages: {
'durationExceeded': 'Videos must be 5 minutes or less',
'fileSizeExceeded': 'Video file is too large (max 50MB)',
},
);
3. Document Attachment #
final config = MediaPickerGuard.documentUploadConfig(
maxSizeMB: 10,
allowedExtensions: ['pdf', 'doc', 'docx', 'txt'],
customErrorMessages: {
'formatNotAllowed': 'Only PDF, Word, and text documents allowed',
},
);
๐ง Advanced Features #
Error Handling Patterns #
// Pattern 1: Simple validation
final result = await MediaPickerGuard.validateFile(file, config: config);
if (!result.isValid) {
showError(result.firstFriendlyErrorMessage);
return;
}
// Pattern 2: Handle specific error types
for (final error in result.errors) {
switch (error.type) {
case ValidationErrorType.fileSizeExceeded:
handleSizeError(error);
break;
case ValidationErrorType.formatNotAllowed:
handleFormatError(error);
break;
default:
handleGenericError(error);
}
}
// Pattern 3: Batch validation with progress
final validFiles = <File>[];
for (int i = 0; i < files.length; i++) {
final isValid = await MediaPickerGuard.isFileValid(files[i], config: config);
if (isValid) validFiles.add(files[i]);
updateProgress(i + 1, files.length);
}
Custom Validation Logic #
// Extend validation with custom logic
Future<bool> validateFileWithCustomRules(File file) async {
// First, run standard validation
final standardResult = await MediaPickerGuard.validateFile(file, config: config);
if (!standardResult.isValid) return false;
// Add custom business logic
if (await isFileAlreadyUploaded(file)) {
showError('This file has already been uploaded');
return false;
}
if (await containsInappropriateContent(file)) {
showError('File content not allowed');
return false;
}
return true;
}
๐ Validation Types #
| Validation Type | Supported Files | Description |
|---|---|---|
| Size | All files | Min/max file size in bytes |
| Duration | Video, Audio | Min/max media duration |
| Extension | All files | Allowed file extensions |
| MIME Type | All files | Allowed MIME types |
| File Access | All files | File accessibility check |
| Integrity | All files | Basic corruption detection |
๐จ Error Types #
| Error Type | Description | User-Friendly Message |
|---|---|---|
fileSizeExceeded |
File too large | "File is too large (2.5MB). Maximum size allowed is 2.0MB." |
fileSizeTooSmall |
File too small | "File is too small (5KB). Minimum size required is 10KB." |
durationExceeded |
Media too long | "Media is too long (12m 30s). Maximum duration allowed is 10m." |
durationTooShort |
Media too short | "Media is too short (5s). Minimum duration required is 10s." |
formatNotAllowed |
Wrong file format | "File format 'txt' is not supported. Supported formats: jpg, png." |
fileNotAccessible |
Cannot access file | "Unable to access the selected file. Please try a different file." |
fileCorrupted |
File corrupted | "File appears to be corrupted. Please try a different file." |
๐ API Reference #
MediaPickerGuard #
Main class for file validation.
Methods
validateFile(File file, {MediaValidationConfig? config})โFuture<MediaValidationResult>validateFilePath(String filePath, {MediaValidationConfig? config})โFuture<MediaValidationResult>validateFiles(List<File> files, {MediaValidationConfig? config})โFuture<Map<String, MediaValidationResult>>isFileValid(File file, {MediaValidationConfig? config})โFuture<bool>getFileInfo(File file)โFuture<Map<String, dynamic>?>
Factory Methods
imageUploadConfig({...})โMediaValidationConfigvideoUploadConfig({...})โMediaValidationConfigaudioUploadConfig({...})โMediaValidationConfigdocumentUploadConfig({...})โMediaValidationConfig
MediaValidationConfig #
Configuration class for validation rules.
Properties
maxSizeBytesโint?- Maximum file size in bytesminSizeBytesโint?- Minimum file size in bytesmaxDurationโDuration?- Maximum media durationminDurationโDuration?- Minimum media durationallowedExtensionsโList<String>?- Allowed file extensionsallowedMimeTypesโList<String>?- Allowed MIME typesmediaTypeโMediaType- Expected media typecustomErrorMessagesโMap<String, String>?- Custom error messages
MediaValidationResult #
Result of validation operation.
Properties
isValidโbool- Whether validation passederrorsโList<MediaValidationError>- List of validation errorsmetadataโMap<String, dynamic>?- Additional file metadatafirstErrorโMediaValidationError?- First error (if any)friendlyErrorMessagesโList<String>- User-friendly error messages
๐ค Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
๐ License #
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Issues #
Found a bug or have a feature request? Please open an issue on GitHub.
๐ Interactive Example App #
We've created a complete Flutter example app that you can run to test all the features:
๐ Quick Start #
# Clone and run the example app
./run_example.sh
Or manually:
cd example_app
flutter pub get
flutter run
๐ฏ Example App Features #
- ๐ฑ Beautiful UI: Material Design interface with intuitive controls
- ๐๏ธ Multiple Validation Types: Switch between Image, Video, Audio, Document, and Custom configurations
- ๐ Multiple File Sources: Pick from gallery, camera, or file system
- โก Real-time Validation: Instant feedback with detailed results
- ๐จ Visual Results: Color-coded success/failure with detailed error messages
- ๐ File Information: Complete file analysis and metadata display
๐ผ๏ธ Screenshots #
The example app includes:
- Validation type selector (Image, Video, Audio, Document, Custom)
- Configuration display showing current validation rules
- File selection buttons (Gallery, Camera, Files)
- Real-time file information display
- Color-coded validation results with detailed error messages
๐ Testing Scenarios #
The app is perfect for testing:
- โ Valid files: Small images, short videos, supported formats
- โ Invalid files: Large files, unsupported formats, long videos
- ๐ Edge cases: Empty files, corrupted files, permission issues
Check out the example_app directory for the complete source code and example for additional usage patterns.
๐ฎ Future Features #
- โ Image dimension validation (width/height)
- โ Video resolution validation
- โ Audio quality/bitrate validation
- โ Cloud storage integration
- โ Batch processing with progress callbacks
- โ Advanced file type detection
- โ Content-based validation (AI/ML integration)
Made with โค๏ธ by the Flutter community