Laravel Validate Array of Files Total Allowable Upload Size
Asked Answered
R

3

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!

Raspberry answered 1/11, 2017 at 12:4 Comment(0)
B
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; 

    });

}
Bitch answered 1/11, 2017 at 14:1 Comment(1)
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???Contrayerva
P
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
Philippe answered 1/11, 2017 at 12:18 Comment(0)
B
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']
    ]);
Bautista answered 24/4, 2024 at 13:9 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.