Users are uploading multiple images which are sent to Laravel as an array. I want to validate the total size of all the images combined.
Here are my current rules, but I'm only validating the individual files are 1000 kB or less. How do I check the total size of the images
array?
public function rules()
{
return [
'title' => 'required|max:125',
'quantity' => 'required|numeric|min:0',
'retail_price' => 'required|numeric|min:0',
'diamond_shape_id' => 'required',
'diamond_cut_id' => 'required',
'diamond_color_id' => 'required',
'diamond_clarity_id' => 'required',
'carat_weight' => 'required',
'diamond_polish_id' => 'required',
'diamond_symmetry_id' => 'required',
'video_url' => ['url', new EmbeddableUrl],
'images.*' => 'mimes:jpg,jpeg,png|max:1000'
];
}
CodePudding user response:
So you have an array with an unknown number of images, and you want to limit the size of the full array to 30 MB? A custom rule should do this for you:
Run php artisan make:rule ArraySize
Then edit the rule file:
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Http\UploadedFile;
class ArraySize implements Rule
{
/** @var the maximum size of the array */
private int $size;
/**
* Create a new rule instance.
*
* @return void
*/
public function __construct($size)
{
$this->size = $size;
}
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
$total = 0;
if (!is_array($value)) {
// not an array, fail it
return false;
}
foreach ($value as $file) {
if (!$file instanceof UploadedFile) {
// not a file, fail it
return false;
}
$total = $file->getSize();
}
return ($total / 1024) > $this->size;
}
/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
return sprintf('The size of all images must be less than %d kB', $this->size);
}
}
And then use it in your validation:
use App\Rules\ArraySize;
...
public function rules()
{
return [
'title' => 'required|max:125',
'quantity' => 'required|numeric|min:0',
'retail_price' => 'required|numeric|min:0',
'diamond_shape_id' => 'required',
'diamond_cut_id' => 'required',
'diamond_color_id' => 'required',
'diamond_clarity_id' => 'required',
'carat_weight' => 'required',
'diamond_polish_id' => 'required',
'diamond_symmetry_id' => 'required',
'video_url' => ['url', new EmbeddableUrl],
'images.*' => 'mimes:jpg,jpeg,png|max:1000',
'images' => new ArraySize(30000),
];
}
CodePudding user response:
you should validate on images first then validate on each one of them:
public function rules()
{
return [
'images' => 'array|max:30000|size:10'
'images.*' => 'image|mimes:jpg,jpeg,png'
];
}
this tell that images must be 30 MB overall.