Skip to content

Instantly share code, notes, and snippets.

@MarkRedeman
Last active December 15, 2016 15:06
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MarkRedeman/9125186 to your computer and use it in GitHub Desktop.
Save MarkRedeman/9125186 to your computer and use it in GitHub Desktop.
<?php
/*
|--------------------------------------------------------------------------
| Max Upload File Size filter
|--------------------------------------------------------------------------
|
| Check if a user uploaded a file larger than the max size limit.
| This filter is used when we also use a CSRF filter and don't want
| to get a TokenMismatchException due to $_POST and $_GET being cleared.
|
*/
Route::filter('maxUploadFileSize', function()
{
// Check if upload has exceeded max size limit
if (! (Request::isMethod('POST') or Request::isMethod('PUT'))) { return; }
// Get the max upload size (in Mb, so convert it to bytes)
$maxUploadSize = 1024 * 1024 * ini_get('post_max_size');
$contentSize = 0;
if (isset($_SERVER['HTTP_CONTENT_LENGTH']))
{
$contentSize = $_SERVER['HTTP_CONTENT_LENGTH'];
}
elseif (isset($_SERVER['CONTENT_LENGTH']))
{
$contentSize = $_SERVER['CONTENT_LENGTH'];
}
// If content exceeds max size, throw an exception
if ($contentSize > $maxUploadSize)
{
throw new GSVnet\Core\Exceptions\MaxUploadSizeException;
}
});
@pedzed
Copy link

pedzed commented Feb 28, 2016

I'd remove throw new GSVnet\Core\Exceptions\MaxUploadSizeException; for obvious reasons.

This snippet is for Laravel 4. Laravel 5 doesn't use filters anymore. I did the following to get it working for Laravel 5(.2):

  1. Create a new method in app/Http/Middleware/VerifyCsrfToken.php:

    /**
     * Max Upload File Size filter
     * 
     * Check if a user uploaded a file larger than the max size limit.
     * This filter is used when we also use a CSRF filter and don't want
     * to get a TokenMismatchException due to $_POST and $_GET being cleared.
     */
    private function _maxUploadFileSize()
    {
        if(!(request()->isMethod('POST') || request()->isMethod('PUT'))) {
            return;
        }
    
        // Get the max upload size (in Mb, so convert it to bytes)
        $maxUploadSize = 1024 * 1024 * ini_get('post_max_size');
        $contentSize = 0;
    
        if(isset($_SERVER['HTTP_CONTENT_LENGTH'])) {
            $contentSize = $_SERVER['HTTP_CONTENT_LENGTH'];
        } else if(isset($_SERVER['CONTENT_LENGTH'])) {
            $contentSize = $_SERVER['CONTENT_LENGTH'];
        }
    
        if($contentSize > $maxUploadSize) {
            throw new \Exception('Max file upload size exceeded.');
        }
    }
  2. Of course you have to call it.

    public function __construct() {
        $this->_maxUploadFileSize();
    }
  3. The problem now is that you ignore the parent constructor. So call that as well.

    public function __construct(Application $app, Encrypter $encrypter) {
        $this->_maxUploadFileSize();
    
        parent::__construct($app, $encrypter);
    }
  4. So the final code:

    <?php
    
    namespace App\Http\Middleware
    {
        use Illuminate\Contracts\Encryption\Encrypter;
        use Illuminate\Foundation\Application;
        use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
        use Illuminate\Http\Request;
    
        class VerifyCsrfToken extends BaseVerifier
        {
            /**
             * The URIs that should be excluded from CSRF verification.
             *
             * @var array
             */
            protected $except = [
                //
            ];
    
            public function __construct(Application $app, Encrypter $encrypter) {
                $this->_maxUploadFileSize();
    
                parent::__construct($app, $encrypter);
            }
    
            /**
             * Max Upload File Size filter
             * 
             * Check if a user uploaded a file larger than the max size limit.
             * This filter is used when we also use a CSRF filter and don't want
             * to get a TokenMismatchException due to $_POST and $_GET being cleared.
             */
            private function _maxUploadFileSize()
            {
                if(!(request()->isMethod('POST') || request()->isMethod('PUT'))) {
                    return;
                }
    
                // Get the max upload size (in Mb, so convert it to bytes)
                $maxUploadSize = 1024 * 1024 * ini_get('post_max_size');
                $contentSize = 0;
    
                if(isset($_SERVER['HTTP_CONTENT_LENGTH'])) {
                    $contentSize = $_SERVER['HTTP_CONTENT_LENGTH'];
                } else if(isset($_SERVER['CONTENT_LENGTH'])) {
                    $contentSize = $_SERVER['CONTENT_LENGTH'];
                }
    
                if($contentSize > $maxUploadSize) {
                    throw new \Exception('Max file upload size exceeded.');
                }
            }
        }
    }

Of course you should change it accordingly to your naming conventions.

Even better would be to throw a custom MaxUploadSizeException exception.

@SimonMARTIN87
Copy link

Thx to you Mark for that great snippet.
About making it work for Laravel 5, a better idea will be to create a Middleware, with your code in the handle() method.
Except you'll have to change the first test in :

if(!(request()->isMethod('POST') || request()->isMethod('PUT'))) { return $next($request); }

After then, you just have to register it in kernel.php. By the way, you need it to run before the VerifyCsrfToken middleware.
So register it in the 'web' group, just before the Csrf line.
Ok, this is a bit "overkill" for the most part of cases, but imo that's the most elegant way to do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment