diff --git a/src/Illuminate/Validation/Rules/File.php b/src/Illuminate/Validation/Rules/File.php index c97f68e476d2..7e9f59b0d0bd 100644 --- a/src/Illuminate/Validation/Rules/File.php +++ b/src/Illuminate/Validation/Rules/File.php @@ -7,6 +7,7 @@ use Illuminate\Contracts\Validation\ValidatorAwareRule; use Illuminate\Support\Arr; use Illuminate\Support\Facades\Validator; +use Illuminate\Support\Str; use Illuminate\Support\Traits\Conditionable; use Illuminate\Support\Traits\Macroable; use InvalidArgumentException; @@ -131,13 +132,13 @@ public static function types($mimetypes) /** * Indicate that the uploaded file should be exactly a certain size in kilobytes. * - * @param int $kilobytes + * @param string|int $size * @return $this */ - public function size($kilobytes) + public function size($size) { - $this->minimumFileSize = $kilobytes; - $this->maximumFileSize = $kilobytes; + $this->minimumFileSize = $this->toKilobytes($size); + $this->maximumFileSize = $this->minimumFileSize; return $this; } @@ -145,14 +146,14 @@ public function size($kilobytes) /** * Indicate that the uploaded file should be between a minimum and maximum size in kilobytes. * - * @param int $minKilobytes - * @param int $maxKilobytes + * @param string|int $minSize + * @param string|int $maxSize * @return $this */ - public function between($minKilobytes, $maxKilobytes) + public function between($minSize, $maxSize) { - $this->minimumFileSize = $minKilobytes; - $this->maximumFileSize = $maxKilobytes; + $this->minimumFileSize = $this->toKilobytes($minSize); + $this->maximumFileSize = $this->toKilobytes($maxSize); return $this; } @@ -160,12 +161,12 @@ public function between($minKilobytes, $maxKilobytes) /** * Indicate that the uploaded file should be no less than the given number of kilobytes. * - * @param int $kilobytes + * @param string|int $size * @return $this */ - public function min($kilobytes) + public function min($size) { - $this->minimumFileSize = $kilobytes; + $this->minimumFileSize = $this->toKilobytes($size); return $this; } @@ -173,16 +174,39 @@ public function min($kilobytes) /** * Indicate that the uploaded file should be no more than the given number of kilobytes. * - * @param int $kilobytes + * @param string|int $size * @return $this */ - public function max($kilobytes) + public function max($size) { - $this->maximumFileSize = $kilobytes; + $this->maximumFileSize = $this->toKilobytes($size); return $this; } + /** + * Convert a potentially human-friendly file size to kilobytes. + * + * @param string|int $size + * @return mixed + */ + protected function toKilobytes($size) + { + if (! is_string($size)) { + return $size; + } + + $value = floatval($size); + + return round(match (true) { + Str::endsWith($size, 'kb') => $value * 1, + Str::endsWith($size, 'mb') => $value * 1000, + Str::endsWith($size, 'gb') => $value * 1000000, + Str::endsWith($size, 'tb') => $value * 1000000000, + default => throw new InvalidArgumentException("Invalid file size suffix."), + }); + } + /** * Specify additional validation rules that should be merged with the default rules during validation. * diff --git a/tests/Validation/ValidationFileRuleTest.php b/tests/Validation/ValidationFileRuleTest.php index 77feb39ed6d0..6ffa71e65bd9 100644 --- a/tests/Validation/ValidationFileRuleTest.php +++ b/tests/Validation/ValidationFileRuleTest.php @@ -205,6 +205,24 @@ public function testMin() ); } + public function testMinWithHumanReadableSize() + { + $this->fails( + File::default()->min('1024kb'), + UploadedFile::fake()->create('foo.txt', 1023), + ['validation.min.file'] + ); + + $this->passes( + File::default()->min('1024kb'), + [ + UploadedFile::fake()->create('foo.txt', 1024), + UploadedFile::fake()->create('foo.txt', 1025), + UploadedFile::fake()->create('foo.txt', 2048), + ] + ); + } + public function testMax() { $this->fails( @@ -223,6 +241,42 @@ public function testMax() ); } + public function testMaxWithHumanReadableSize() + { + $this->fails( + File::default()->max('1024kb'), + UploadedFile::fake()->create('foo.txt', 1025), + ['validation.max.file'] + ); + + $this->passes( + File::default()->max('1024kb'), + [ + UploadedFile::fake()->create('foo.txt', 1024), + UploadedFile::fake()->create('foo.txt', 1023), + UploadedFile::fake()->create('foo.txt', 512), + ] + ); + } + + public function testMaxWithHumanReadableSizeAndMultipleValue() + { + $this->fails( + File::default()->max('1mb'), + UploadedFile::fake()->create('foo.txt', 1025), + ['validation.max.file'] + ); + + $this->passes( + File::default()->max('1mb'), + [ + UploadedFile::fake()->create('foo.txt', 1000), + UploadedFile::fake()->create('foo.txt', 999), + UploadedFile::fake()->create('foo.txt', 512), + ] + ); + } + public function testMacro() { File::macro('toDocument', function () {