christopher's avatar

jQuery-File-Upload with Laravel

Does anyone has a good tutorial or can say how to use the jQuery-File-Upload with Laravel ?

-> https://github.com/blueimp/jQuery-File-Upload

Maybe this would be also a good Screencast for Jeff.

0 likes
15 replies
bashy's avatar

Just put the HTML into a view, link the Javascript and make a "post" route. Make sure you return any errors into json. return Response::json();

$input = Input::all();

if ( ! \Media::isValidUpload($input))
{
   return Response::json(array(\Media::$errors->all()), 400);
}

Then with validation passing, you can grab the file(s) data with

$file = Input::file('file');

$file->getClientOriginalName();
$file->getClientOriginalExtension();
$file->getSize();

Etc etc etc

christopher's avatar

Currently i pasted the HTML and JS to my view just to try it out particularly because the progress bar but this does not work.

Here is my view -> http://laravel.io/bin/nXr4W

In my routes i have

 Route::post('{id}/albums/create',array('as'=>'upload', 'before'=>'auth','uses'=>'AlbumController@store'));

jquery is loaded in the header and bootstrap.js in the footer

bashy's avatar

Okay, so what "does not work"? Do you perform a POST? Have you checked dev tools to see the response?

christopher's avatar

The error console says

Uncaught TypeError: Cannot read property 'fileupload' of undefined jquery.fileupload-jquery-ui.js:27(anonymous function)

bashy's avatar

That's Javascript then. I'd sort out that first as that's not a Laravel issue.

I personally used DropzoneJS instead of that library, found it better for multiple uploads with extra fields. http://www.dropzonejs.com (I have this working with Laravel as well)

christopher's avatar

Ok then i would use Dropzone as file upload. I found here a laravel example for dropzone -> https:// github.com/sseffa/l4_file_upload

1 like
bashy's avatar

Relevant part is

// upload file
Route::post('/upload', function () {

    $file = Input::file('file');

    if($file) {

        $destinationPath = public_path() . '/uploads/';
        $filename = $file->getClientOriginalName();

        $upload_success = Input::file('file')->move($destinationPath, $filename);

        if ($upload_success) {

            // resizing an uploaded file
            Image::make($destinationPath . $filename)->resize(100, 100)->save($destinationPath . "100x100_" . $filename);

            return Response::json('success', 200);
        } else {
            return Response::json('error', 400);
        }
    }
});

As you can see, it's using Response::json so the uploader can return the error array to the HTML view. For multiple files, it does a POST request per file (which is good for custom file labels or inputs for each file). I require the user to add a label for each image, saves them adding one for each after uploading.

1 like
commandantp's avatar

Hi! Quick one, should we not re-validate the file type since it has done only in front end/client side?

bashy's avatar

You definitely should, check a few replies up.

$input = Input::all();

if ( ! \Media::isValidUpload($input))
{
    return Response::json(array(\Media::$errors->all()), 400);
}
2 likes
commandantp's avatar

My bad! Thanks! Damn dropzone is reaaaally easy to use another dev had put plupload in the app and it is a nightmare to work with +_+

bashy's avatar

Yes it's real nice for the client/frontend user as well :)

commandantp's avatar

Question: so far I have been doing this for uploading on aws s3

$avatar = Image::make($avatar);
$path_to_temp_file = $avatar->dirname . '/' . $avatar->filename;
$uploadSuccess = $s3->putObject(array(
                            'Bucket' => $bucket,
                            'Key' => $key,
                            'SourceFile'=> $path_to_temp_file
                        ));

Do you know if there is a way to avoid the temp and send directly to aws from the user ? Not sure if this is the appropriate place to ask if needed I can open a thread.

bashy's avatar

I guess a new thread would be better. Not used AWS but the tmp file is only so you can move it if you want the file.

AlexanderZon's avatar

in your controller put there

public function postUpload(){

    $files = Input::file('files');

    $json = array(
        'files' => array()
        );

    foreach( $files as $file ):

        $filename = $file->getClientOriginalName().".".$file->getClientOriginalExtension();

        $json['files'][] = array(
            'name' => $filename,
            'size' => $file->getSize(),
            'type' => $file->getMimeType(),
            'url' => '/uploads/files/'.$filename,
            'deleteType' => 'DELETE',
            'deleteUrl' => self::$route.'/deleteFile/'.$filename,
            );

        $upload = $file->move( public_path().'/uploads/files', $filename );


    endforeach;

    return Response::json($json);

}

And replace your upload route

        var initFileupload = function () {

            $('#fileupload').fileupload({
                // Uncomment the following to send cross-domain cookies:
                //xhrFields: {withCredentials: true},
                url: '{{$route}}/upload',
                autoUpload: true,
                success: function(data){
                    console.log(data);
                }
            });

            // Upload server status check for browsers with CORS support:
            if ($.support.cors) {
                $.ajax({
                    url: '{{$route}}/upload',
                    type: 'HEAD'
                }).fail(function () {
                    $('<span class="alert alert-error"/>')
                        .text('Upload server currently unavailable - ' +
                        new Date())
                        .appendTo('#fileupload');
                });
            }
        }

1 like

Please or to participate in this conversation.