Search code examples
phplaravellaravel-4csrfplupload

Laravel 4 TokenMissMatchException with Plupload


I'm trying to upload files with Plupload but I always get TokenMissMatchException.

// Route
Route::post("/posts/gallery", "PostsController@uploadGallery");
// Controller action
    public function uploadGallery(){
        $file = Input::file('file');
        $destinationPath = public_path() . '/imgs';
        $extension = $file->getClientOriginalExtension();
        $filename = "post-" . str_random(12) . "." . $extension;

        $inFile = $file->getRealPath();
        $outFile = public_path() . "/imgs/" . $filename;

        $image = new Imagick($inFile);
        $image->thumbnailImage(550, 0);
        if($image->writeImage($outFile)){
            return Response::json(["response" => "ok", "img" => $filename]);
        }else{
            return Response::json(["response" => "error"]);
        }
    }

This is my attempt to fix this. I tried to add _token to request but it's not picking it up:

$("#uploader").pluploadQueue({
            runtimes : 'html5,flash,silverlight,html4',
            url : "{{ URL::action('PostsController@uploadGallery') }}",
            chunk_size: '1mb',
            rename : true,
            dragdrop: true,

            filters : {
                max_file_size : '3mb',
                mime_types: [
                    {title : "Image files", extensions : "jpg,gif,png"},
                ]
            },
            resize : {width : 320, height : 240, quality : 90},
            flash_swf_url : "<?php echo public_path() . '/js/Moxie.swf'; ?>",
            silverlight_xap_url : "<?php echo public_path() . '/js/Moxie.xap'; ?>",
            prevent_duplicates: true,
            multipart_params : {
                "_token" : $("[name=_token]").val()
            }
        });

In filters.php I have this:

Route::filter('csrf', function() {
    $token = Request::ajax() ? Request::header('x-csrf-token') : Input::get('_token');
    if (Session::token() != $token){
        throw new Illuminate\Session\TokenMismatchException;
    }
});

Can someone help me with this?

UPDATE:

Html form for uploading files:

<div class="imageGallery">
    {{ Form::open() }}
        <div id="uploader">
            <p>Your browser doesn't have Flash, Silverlight or HTML5 support.</p>
        </div>
    {{ Form::close() }}
</div>

// hidden input field

<input type="hidden" value="VJRUpvq92oYxCsNHVBi5TqqkU6I6CQayay6x7L0m" name="_token">

Solution

  • If the upload is being done via ajax, your csrf filter is expecting the token to be in the 'x-csrf-token' header, not the input.

    Instead of adding the token to the multipart_params, try adding it to the headers:

    $("#uploader").pluploadQueue({
        runtimes : 'html5,flash,silverlight,html4',
        url : "{{ URL::action('PostsController@uploadGallery') }}",
        chunk_size: '1mb',
        rename : true,
        dragdrop: true,
        filters : {
            max_file_size : '3mb',
            mime_types: [
                {title : "Image files", extensions : "jpg,gif,png"},
            ]
        },
        resize : {width : 320, height : 240, quality : 90},
        flash_swf_url : "<?php echo public_path() . '/js/Moxie.swf'; ?>",
        silverlight_xap_url : "<?php echo public_path() . '/js/Moxie.xap'; ?>",
        prevent_duplicates: true,
        headers: {
            "x-csrf-token" : $("[name=_token]").val()
        }
    });
    

    Edit

    In addition to the above change, it was determined that the javascript was not finding the _token input element to get the value. The solution to that issue was to add quotes around the value in the CSS attribute selector.

    The javascript that ended up working:

    $("input[name='_token']").val()
    

    The CSS3 docs regarding attribute selectors can be found here. Although some browsers work without the quotes, the examples they provide show the selector values being quoted.