validateXFile static method
Validate XFile (from image_picker)
Returns true if valid, false otherwise with error message
Implementation
static Future<({bool isValid, String? error})> validateXFile(
XFile xFile,
) async {
try {
// Get file size by reading bytes
final bytes = await xFile.readAsBytes();
final fileSize = bytes.length;
const maxSize = 10 * 1024 * 1024; // 10MB
if (fileSize > maxSize) {
return (isValid: false, error: 'File size exceeds 10MB');
}
if (fileSize == 0) {
return (isValid: false, error: 'File is empty');
}
// Check file extension and mimeType
bool isValidFormat = false;
final validExtensions = ['jpg', 'jpeg', 'png', 'heic', 'heif', 'webp'];
// First, try to validate by extension
try {
final path = xFile.path;
if (path.isNotEmpty && path.contains('.')) {
final extension = path.split('.').last.toLowerCase();
if (validExtensions.contains(extension)) {
isValidFormat = true;
}
}
} catch (e) {
// Extension check failed, will try mimeType
}
// If extension check didn't pass, try mimeType
if (!isValidFormat) {
try {
final mimeType = xFile.mimeType;
if (mimeType != null) {
// Check if it's an image mime type
if (mimeType.startsWith('image/')) {
// Extract format from mimeType (e.g., "image/png" -> "png")
final mimeFormat = mimeType.split('/').last.toLowerCase();
if (validExtensions.contains(mimeFormat) ||
mimeFormat == 'png' ||
mimeFormat == 'jpeg' ||
mimeFormat == 'jpg') {
isValidFormat = true;
}
}
}
} catch (e) {
// mimeType check also failed
}
}
// If still not valid, check by file signature (magic numbers)
if (!isValidFormat) {
try {
// Check first few bytes for image signatures
final signature = bytes.take(8).toList();
// PNG signature: 89 50 4E 47 0D 0A 1A 0A
if (signature.length >= 8 &&
signature[0] == 0x89 &&
signature[1] == 0x50 &&
signature[2] == 0x4E &&
signature[3] == 0x47) {
isValidFormat = true;
}
// JPEG signature: FF D8 FF
else if (signature.length >= 3 &&
signature[0] == 0xFF &&
signature[1] == 0xD8 &&
signature[2] == 0xFF) {
isValidFormat = true;
}
// WebP signature: Check for "RIFF" and "WEBP"
else if (bytes.length >= 12 &&
String.fromCharCodes(bytes.take(4)) == 'RIFF' &&
String.fromCharCodes(bytes.skip(8).take(4)) == 'WEBP') {
isValidFormat = true;
}
} catch (e) {
// Signature check failed
}
}
if (!isValidFormat) {
return (
isValid: false,
error:
'Invalid file format. Supported: ${validExtensions.join(", ")}',
);
}
return (isValid: true, error: null);
} catch (e) {
return (isValid: false, error: 'Error validating file: ${e.toString()}');
}
}