0

I've completed a tutorial to upload image files. How can I validate file uploads in the view when a user uploads a file larger than 2MB?

create.blade.php

@if (count($errors) > 0)
    <div class="alert alert-danger">
        <strong>Whoops!</strong> Errors.<br><br>
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif
@if(session('success'))
    <div class="alert alert-success">
        {{ session('success') }}
    </div>
@endif
<div class="form-group">
    <input type="file" name="photos[]" multiple aria-describedby="fileHelp"/>
    <small id="fileHelp" class="form-text text-muted">jpeg, png, bmp - 2MB.</small>
</div>

Rules

public function rules()
{
    $rules = [
        'header' => 'required|max:255',
        'description' => 'required',
        'date' => 'required',
    ];
    $photos = $this->input('photos');
    foreach (range(0, $photos) as $index) {
        $rules['photos.' . $index] = 'image|mimes:jpeg,bmp,png|max:2000';
    }

    return $rules;
}

Everything is ok, however when I try to upload a file which is larger than 2MB it gives me an error:

Illuminate \ Http \ Exceptions \ PostTooLargeException No message

How can I solve this and secure this exception?

Morphed
  • 3,527
  • 2
  • 29
  • 55
Giacomo
  • 341
  • 2
  • 8
  • 25

4 Answers4

2

in laravel you can not handle this case in controller as it will not get to controller/customrequest and will be handled in middleware so you can handle this in ValidatePostSize.php file:

public function handle($request, Closure $next)
 {
  //       if ($request->server('CONTENT_LENGTH') > $this->getPostMaxSize()) 
            {
             //            throw new PostTooLargeException;
  //        }

   return $next($request);
 }



/**
 * Determine the server 'post_max_size' as bytes.
 *
 * @return int
 */
protected function getPostMaxSize()
{
    if (is_numeric($postMaxSize = ini_get('post_max_size'))) {
        return (int) $postMaxSize;
    }

    $metric = strtoupper(substr($postMaxSize, -1));

    switch ($metric) {
        case 'K':
            return (int) $postMaxSize * 1024;
        case 'M':
            return (int) $postMaxSize * 1048576;
        default:
            return (int) $postMaxSize;
    }
}

with your custom message

Or in App\Exceptions\Handler:

   public function render($request, Exception $exception)
   {
      if ($exception instanceof \Illuminate\Http\Exceptions\PostTooLargeException) {
        // handle response accordingly
      }
      return parent::render($request, $exception);
   }

Else need to update php.ini

upload_max_filesize = 10MB

If you dont to work with any of above solutions you can use client side validation like if you are using jQuery e.g.:

$(document).on("change", "#elementId", function(e) {
 if(this.files[0].size > 7244183)  //set required file size 2048 ( 2MB )
  { 
     alert("The file size is too larage");
    $('#elemendId').value = ""; 
  }
});

or

<script type="text/javascript"> 
 function ValidateSize(file) { 
   var FileSize = file.files[0].size / 1024 / 1024; // in MB 
   if (FileSize > 2) { 
     alert('File size exceeds 2 MB'); 
      $(file).val(''); //for clearing with Jquery 
   } else { 

   } 
 } 
</script>
kshitij
  • 642
  • 9
  • 17
  • I'm just trying your hints, but the first two didn't bring any effect. I will try JQuery – Giacomo Nov 28 '18 at 10:14
  • Let me update my answer for first option and kindly try again if it works and use values accordingly @Giacomo – kshitij Nov 28 '18 at 10:18
  • Ok, better: Warning: POST Content-Length of 10185211 bytes exceeds the limit of 8388608 bytes in Unknown on line 0. I have image limited to 2MB in upload request. What now? :P – Giacomo Nov 28 '18 at 10:46
  • Now you can manipulate the value of file size in the protected function. Need to return the file size from that function and when file more than that size is uploaded you can just return back()->with('error','Custom error for user'); – kshitij Nov 28 '18 at 10:52
  • Logic in the file is if you want to use 'post_max_size' and change value according to that but if you dont want that, just return a size value to compare in top function. – kshitij Nov 28 '18 at 10:53
  • But this function is returning post max size: return (int) $postMaxSize; but how can I compare the maximum value with the value of the entered file. I dont understand this. – Giacomo Nov 28 '18 at 11:02
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/184394/discussion-between-kshitij-and-giacomo). – kshitij Nov 28 '18 at 11:12
1

you have validate image in $rules. try this code:

$this->validate($request,[
                'header' => 'required|max:255',
                'description' => 'required',
                'date' => 'required',
                'photos.*' => 'image|mimes:jpeg,bmp,png|max:2000',
    ]);
Bhoomi Patel
  • 777
  • 10
  • 32
0

Laravel uses its ValidatePostSize middleware to check the post_max_size of the request and then throws the PostTooLargeException if the CONTENT_LENGTH of the request is too big. This means that the exception if thrown way before it even gets to your controller.

What you can do is use the render() method in your App\Exceptions\Handler e.g.

public function render($request, Exception $exception){
   if ($exception instanceof PostTooLargeException) {
      return response('File too large!', 422);
   }

   return parent::render($request, $exception);
}

Please note that you have to return a response from this method, you can't just return a string like you can from a controller method.

The above response is to replicate the return 'File too large!'; you have in the example in your question, you can obviously change this to be something else.

Hope this helps!

MD. Jubair Mizan
  • 1,539
  • 1
  • 12
  • 20
0

You can try with putting a custom message inside message() message or add PostTooLargeException handler in Handler class. Something like that:

public function render($request, Exception $exception)
{
...
    if($exception instanceof PostTooLargeException){
                return redirect()->back()->withErrors("Size of attached file should be less ".ini_get("upload_max_filesize")."B", 'addNote');
        }
...
}
Kikolce
  • 181
  • 1
  • 1
  • 8