Home > Mobile >  How to validate the total size of an array of uploaded files?
How to validate the total size of an array of uploaded files?

Time:12-21

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.

  • Related