Update! To adapt this code to Laravel 4 please see my newer post here: http://maxoffsky.com/code-blog/uploading-files-in-laravel-4/

In this short blog post I will share with you how I made queued multiple file upload possible with Laravel and a nice jQuery plugin called Dropzone.js.

I needed to give the user the ability to upload multiple images at once and instantly see visual feedback on the upload progress and/or errors that come up during the upload.

Dropzone.js comes with nice CSS and Javascript that make it a breeze to work with HTML 5 file upload API. It provides you with a file input container that users can drag and drop files unto or just click the container to select multiple files from the file system.

From the plugin docs: Dropzone.js works in :

  • Chrome 7+
  • Firefox 4+
  • IE 10+
  • Opera 12+ (Currently disabled for MacOS because their API is buggy)
  • Safari 5+

For all the other browsers, dropzone provides an oldschool file input fallback.

To implement this awesome plugin here is what you need to do :

1) Download Dropzone.js Javascript and CSS and reference to them from your view (or layout):

{{ HTML::style('css/basic.css');}}
{{ HTML::script('js/vendor/dropzone.js') }}

2) In your view have a form element with class dropzone, action being the path to your upload route or controller and some id:

Upload using Dropzone.js

<form action="{{ url('user/upload')}}" class="dropzone" id="my-awesome-dropzone"></form>

At this point if you go to the view where you implemented the dropzone plugin you should see it working. But it should give you errors when you try to upload files because the action where it tries to upload doesn’t exist yet. Now we need to hook up the form to a route or controller.

I have a controller called “user”, and the action that I need to build should do the following things:

  • Validate my file upload to be an image (if I want only images) and below certain size limit in kilobytes.
  • If the validation passes, upload the file and rename it to a random string to avoid collisions.
  • If validation does not pass return the first error to the user and return status code 400.
  • Upon file upload success make a JSON response with code 200 (because 200 is commonly used as a success response)
  • Otherwise throw an error letting the user know that there was a server error.

Now that I have my algorithm figured out, I build the controller action :

	public function post_upload(){

		$input = Input::all();
		$rules = array(
		    'file' => 'image|max:3000',
		);

		$validation = Validator::make($input, $rules);

		if ($validation->fails())
		{
			return Response::make($validation->errors->first(), 400);
		}

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

        $extension = File::extension($file['name']);
        $directory = path('public').'uploads/'.sha1(time());
        $filename = sha1(time().time()).".{$extension}";

        $upload_success = Input::upload('file', $directory, $filename);

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

Side note, make sure you create a folder called “uploads” in the public folder because other files and folders will be created there.

Now if you have your routes set up as mine (a user controller must be registered in the routes) and this action implemented you should see that the files are uploaded successfully and if you navigate to your public/uploads folder you should see something like this:

That’s it!

If you need the files to be resized/cropped before saving, make sure you check out some bundles on bundles.laravel.com, specifically :

http://bundles.laravel.com/bundle/resizer

Let me know if you have any questions/problems with this.

The following two tabs change content below.

Maks Surguy

Full stack web developer, speaker and writer.
Maks is young and energetic breakdancer turned into web developer who lives in Seattle area with his wife. He is well-versed in three languages (English, Russian, Ukrainian) and a dozen of programming languages.