Qlic's avatar
Level 18

The correct method for validating upload array size

Hi,

I have been searching on google and laracasts for a bit now, and although i do find simmilair posts, none is giving a clear answer.

This is the issue, i have a form, which contains a file input field declared as an array since i can append additional fields to it. When using small files (images, pdf, doc, xls etc.) it works properly and the files get uploaded as they should. When uploading larger files (larger than my php.ini settings), i get the token mismatch error caused by the fact that the $_POST is emptied.

So i'm trying to validate the uploaded files before the token error occurs, but so far without luck. I tried a middleware first, but when the file is to large, it's already null before it reaches the middleware. Next i tried validating it on the request, as 'attachments' => 'array|max:2000|mimes:jpg,jpeg,png,bmp,pdf,doc,xls', but that fails since it's an array.

So i'm a bit at a loss, do i have to perform in in a manual route instead of a controller? I did find post similair to my issue, but i don't "understand" the solution posted by @usman (https://laracasts.com/discuss/channels/general-discussion/image-validation).

Anyway, here is my current code inside my ProjectController:

if (Request::hasFile('attachments'))
{
    foreach (Request::file('attachments') as $file)
    {
        if ($file->isValid())
        {
            $fileName = time() .'_'. md5($file->getClientOriginalName()) .'.'. $file->getClientOriginalExtension();
            Storage::put('project/'. $id .'/'. $fileName, file_get_contents($file));
            ProjectAttachment::create(['project_id' => $id, 'name' => $fileName]);

            if (substr(File::mimeType($file), 0, 5) == 'image')
            {
                $this->attachmentThumb(file_get_contents($file), $id, $fileName, 100, 100);
            }
        }
    }
}
0 likes
5 replies
deadlockgB's avatar

You should first validate if the attachments are an array:

$v = Validator::make(
    compact('attachments'),
    'attachments' => 'array|max:2000');

Then check the attachments again with the each function:

if($v->passes())
{
    $v->each('attachments', 'mimes:jpg,jpeg,png,bmp,pdf,doc,xls');
    if($v->passes())
    {
        //Saul Goodman
    }
}
Qlic's avatar
Level 18

Where do i perform that check? Inside my ProjectRequest file?

Qlic's avatar
Level 18

Bump again, is anyone was able to find a proper example / tutorial on this?

Kryptonit3's avatar

untested, refer to my logic for how I would possibly do it client side.

<script>
$(function(){

    $('form').on('submit',function(e){
        // stop form from submitting until we check total file size
        e.preventDefault();
        
        $form = $(this);
        
        // change to allowed total size in MB
        allowedSize = 20;
        
        // set needed variable
        var size = 0;
        
        // Loop through each file input
        $('form input[type="file"]').each(function(i) {

            // Get an array of the files for this input (in case your input allows multiple file selection)
            var files = $(this).get(0).files;

            // Loop through files
            for (var j=0; file = files[j]; j++) {

                // File size, in bytes
                var size = size + file.size;
            }
        });
        
        if(size == 0) {
            alert('You must upload at least one file!');
        }
        
        // convert size (currently in bytes) to MB
        var sizeMB = size / 1048576; // 1048576 bytes in 1 MB
        
        if(sizeMB > allowedSize) {
            alert('Total file size exceeds current limit! Limit: '+allowedSize+'MB');
        }
        
        // everything checks out, submit the form
        
        $form.get(0).submit();
        
    });

});

</script>

<form>
    <input type="file" name="file[]" />
    <input type="file" name="file[]" />
    <input type="file" name="file[]" />
</form>

Please or to participate in this conversation.