9

My View has an array of file inputs like

<input type="file" name="videos[]" />
<input type="file" name="videos[]" />
...
...

and I want to validate for the total allowable upload size (Eg: Total Allowable Upload limit is 3Mb). I've written the validation like

$validatedData = $request->validate([
     'videos.*' => 'present|file|mimetypes:video/mp4,video/ogg|max:3000',
]);

but this validates for 3Mb per video.

I've tried

$validatedData = $request->validate([
    'videos' => 'file|max:3000',
    'videos.*' => 'present|file|mimetypes:video/mp4,video/ogg|max:3000',
]);

/*------------------------------------------------*/

$validatedData = $request->validate([
    'videos' => 'array|max:3000',
    'videos.*' => 'present|file|mimetypes:video/mp4,video/ogg|max:3000',
]);

but the validation is not working for total upload size greater than 3Mb. Do I have to write a Custom Validation Rule to validate the total uploaded file size limit. Or is there any predefined validation rule? Any help appreciated.

Thank You!

3 Answers 3

15

I think the best way to validate the total size is by adding a custom validation rule, here is how to do that:

In your controller:

$validatedData = $request->validate([
    'videos' => 'array|max_uploaded_file_size:3000',
    'videos.*' => 'present|file|mimetypes:video/mp4,video/ogg',
]);

Register custom validation in AppServiceProvider.php

public function boot() {

    Validator::extend('max_uploaded_file_size', function ($attribute, $value, $parameters, $validator) {
        
        $total_size = array_reduce($value, function ( $sum, $item ) { 
            // each item is UploadedFile Object
            $sum += filesize($item->path()); 
            return $sum;
        });

        // $parameters[0] in kilobytes
        return $total_size < $parameters[0] * 1024; 

    });

}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much for this, I've been searching for something like this earlier but never found this method. Wondering why the h*ck it isn't mentioned in the official validation documentation???
0

Not a very elegant solution but, I would foreach the videos and use the php filesize function (returns integer size in bytes)

3mb = 3,145,728,000 bytes

foreach($request['videos'] as $video){
$size = filesize($video);
if($size > 3145728000)
return Redirect::back()->withErrors(['msg', 'The Message']);

and inside your view call this

@if($errors->any())
<h4>{{$errors->first()}}</h4>
@endif

Comments

0

Have solved it as follows which is probably not the way it should be done.

The controller receives scans of an agreement (required) and (possibly) other files, referred to as otra.

The code below makes a new variable $totalsize in which it adds the size of the individual files. The variable is divided by 1000 to convert from bytes to kb and rounded and cast as an integer for validation (couldn't validate a double type variable).

Subsequently that variable is inserted in the request for validation and validated against a max of 2048kb.

 public function submit(Request $request)
{
    $totalsize = $request->agreement->getsize();
    if ($request->file('otra')) {
        foreach ($request->file('otra') as $file) {
            $totalsize += $file->getsize();
        }
    }
    $totalsize = (int) round($totalsize / 1000);

    $request->request->add(['totalsize' => $totalsize]);  // add to request

    $validator = Validator::make($request->all(), [
        'email'            => ['required', 'email'],
        'agreement' => ['required', 'mimes:pdf'],
        'name'             => ['required'],
        'otra.*'           => ['mimes:jpg,jpeg,png,pdf'],
        'totalsize'        => ['integer', 'max:2048']
    ]);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.