Howto : AJAX multiple file upload in Laravel (3)

Update! To adapt this code to Laravel 4 please see my newer post here: https://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 in PHP before saving, make sure you check out some packages on Packagist, specifically :

http://intervention.olivervogel.net/

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

You may also like

  • ben

    Thanks for all the Laravel Tutorials. Keep them coming!

  • Hi,

    Thanks for this tutorial but your form’s HTML is not displayed correctly. It should be like below;

    And if you enabled CSRF protection, which you must, then you have to insert token in your form;

    {{ Form::token() }}

  • WordPress messed my previous comment. The HTML form should be;

    form id=”my-awesome-dropzone” action=”{{ url(‘user/upload’) }}” class=”dropzone”

  • Vaqas

    Can you please share a tutorial where we can show the save image with the post, Like you made the blog tutorial if some one want to publish the image with post how we can do that ? I am waiting for your positive response.

    Thanks

    Regards,

  • on ln 18 you have $directory = path(‘public’).’uploads/’.sha1(time());

    Does anyone know in Laravel4, how to access path()? It does not appear to be present.

  • Maks Surguy

    just try to do ‘public/uploads’ instead of using “path(public).’uploads'”.

  • Vaqas Uddin

    If I dont want to create new folder just saving all files in one folder how I can do that?

  • Maks Surguy

    Just replace
    path(‘public’).’uploads/’.sha1(time());

    with

    path(‘public’).’uploads/yourfolder’);

    =)

  • Pingback: Sürükle Bırak Resim Yükleme Aracı – Dropzone.js | Nefdata()

  • Pingback: Sürükle Bırak Dosya Yükleme Aracı – Dropzone.js | Nefdata()

  • Gabriel

    Hi, thank you for your tutorial, works perfectly.

    Sometimes i need to upload only one file and prevent multiple choice. I can’t find how i can do that with dropzone.

    Is it possible?

    Thank you one file

  • Maks Surguy

    I have searched its documentation and I don’t think you can do that with dropzone.
    As a better alternative for AJAX style uploads I recommend this – http://malsup.com/jquery/form/#file-upload

  • andsien

    Hi thanks for this turorial. One thing, iv got problems when image width dimension is above 2031 px. I wont upload and give no error message on the dropzone. The green check mark is shown but wont upload. Thanks, Hope you can help me on this.

  • Maks Surguy

    That probably is the PHP upload limit issue. Try increasing the max size of file uploads

  • triezrjas

    Hi I’m new to Laravel and your code helped me a lot. My problem after uploading files is to show or view the list of files uploaded. I hope you can help me. 🙂

  • Maks Surguy

    Are you using Laravel 3 or 4 ?
    I prefer to save information about the uploaded files into the database and then just showing the items from the database

  • Pingback: Uploading files in Laravel 4 - Maxoffsky |()

  • Rudra

    How to add Remove per file and remove all files option …
    Thanks in Advance

  • Maks Surguy

    You would have to make that as a separate AJAX call to the server. Let’s say your user is logged in, then from the page with file uploads you make a POST request to your application’s API or controller action with the ID of the file, and on the server side you have to make sure that this file indeed belongs to the user and then you can use Laravel’s file removal function to remove the file.

    Does that solve your question?

  • web

    no doubt good work.
    Can you give a zipped example… not only files to configure.
    one i can put on server and emediately see it working without making upload folder and the like.

    it will be a 1000 times better than tutorial.
    or please email me such zipped at webuzy at yahoo of com

  • Maks Surguy

    I am sorry, I don’t have the complete example ready to be shared in full. The example that I had transformed into a full application : http://fldrp.me

  • RHeno

    {“error”:{“type”:”Symfony\Component\HttpKernel\Exception\NotFoundHttpException”,”message”:””,”file”:”C:\xampp-portable\htdocs\jamshop\bootstrap\compiled.php”,”line”:4921}}

    What The Problem?

  • Maks Surguy

    try running “composer dump-autoload”
    and “php artisan optimize”
    commands

  • Your links to Dropzone website are broken in this post…

  • Hey Marks Im confused with the route, always recibe a 500 internal Server Error

    this is my route
    Route::get(‘/’, function()
    {
    return View::make(‘home.index’);
    });

    Route::post(‘user/upload’, ‘user@upload’);

    …..
    and my controller

    ‘image|max:3000’,
    …..

    what is wrong in the code ?
    can u help me?

  • Maks Surguy

    Which version of Laravel are you using ?
    If using Laravel 4 please follow the link I just posted at the top of this post that says “Update …” because in Laravel 4 things are a bit different

  • Hello there, I want to ask if possible to show image that already uploaded and saved in database to dropzone? I means when we refresh the page, the image that was saved in database is still show in the dropzone area.
    #sory for bad english

  • ohh sorry I dont recibe a mail for you reply… ist both l3 and l4 … its the same error POST http://upload-l4/user/upload 500 (Internal Server Error)

    I confused in the route part …
    this is my route file

    Route::get(‘/’, function()
    {
    return View::make(‘hello’);
    });

    Route::post(‘user/upload’, ‘HomeController@upload’);

  • Pingback: Saeed Pourali - Web and Software design and development()

  • KMJ

    Thanks used this as base for Zend 2 version.

  • Sorry, If anybody are implemented this dropzone.js and can help me?.

    I need some changes but Im not professional with Javascript.

    I need upload only ONE photo a time, and when the foto is right upload show button to aks to the cliente ‘Is this the photo?, and press OK then jumping automaticaly to my process page in php to recording the register in the database with Mysql.

    Please help me.

    Francisco (from Spain)
    (excuse me my bad english)

  • pankaj thakur

    Hello,
    It,s good work. but if any user upload wrong file then there should be option for remove file. is it possible with this plugin?
    if yes then how???? 😮

  • Maks Surguy

    The new version of the plugin allows this, you have to use addRemoveLinks option to be true:

    var myDropzone = new Dropzone("#screenshots-dropzone",{
    url: "{{url('admin/screenshots/upload')}}",
    addRemoveLinks: true,
    maxFiles : 4,
    acceptedFiles: 'image/*',
    maxFilesize: 5
    });

    And then create a handler to send a POST request on item removal:
    myDropzone.on("removedfile", function(file) {
    if(file.xhr){
    var url = JSON.parse(file.xhr.response);
    var imagepath = url.url;
    $.post( "{{url('admin/screenshots/remove')}}",{ url : imagepath });
    }
    myDropzone.options.maxFiles++;
    });

    And of course add the backend routes for the actual process to remove the files…

  • Chris

    In laravel 4 its public_path()

  • Shif

    HI, I’m totally new to laravel! How should I have the route for this?

  • You would place it into a POST route that you define like this:
    Route::post(‘upload’, function(){
    //place code here
    })

  • Hi Maks, I want to integrate your excellent code snippet into my app. The problem I am having is that I rename each file to a random file name and want to store some meta information about each file in the db. However, I have no idea how to detect in the dom, which image was clicked so I can configure its meta info in another form (because I’ve renamed it). Can u help me?

  • sandeep

    i have the same question… especially when i tried to use dropzonejs on iOS, all the photographs that we select will upload with the same name “image.jpg”, which caused the collisions and only the final image file will be uploaded into the uploads folder. adding the random content to the files while uploading resolved the issue. but it caused an other problem.. i.e. the delete links not working on the images as the images uploaded into the folder are of different names that are there in dropzone.

  • Joseph Rex

    One thing I noticed was you had dropped just “dropzonejs.com” in your anchor’s href. This makes it see it as being relative to your website. It should be “http://dropzonejs.com” to reference it properly. Thanks for the tutorial anyway

  • Luka Čavić

    Hello, I have a form for ading a new task, and that task has images…I want to integrate field (dropzone) inside current form (add task), so when I click “Save task”, images start to load, after loading…becouse I want to save image info to db for accessing later.

  • maxsurguy

    Ok, what exactly is your question?

  • Christopher

    How to store the files to the database ? ( e.g the path of the image and an ID )

  • maxsurguy

    You would do that by storing the $directory and the $filename in the DB. For example I would have a table called “items” and have columns “path” and “filename” that I’d insert those values into. Hope that helps!

  • Fadi Fannoun

    Thanks for your effort

    I’ve got this exception: TokenMismatchException

  • maxsurguy

    That means you have a CSRF filter on that route and you need to also pass a CSRF token with the file payload.

  • Luka Čavić

    How to do that? 🙂 My email is luka . cavic @ gmail . com – Can I contact you for help with this? 🙂

  • Miro Hristov

    Thanks a lot! You rock!

    In laravel 4.2 you can use the form helper:
    {{Form::open(array(‘url’ => ‘users/upload’, ‘method’ => ‘POST’, ‘files’ => ‘true’, ‘data-ajax’ => ‘ture’, ‘class’ => ‘dropzone’))}}
    {{ Form::close() }}

  • Koyix

    I’m always get error with this : Class ‘AppHttpControllersFile’ not found

    Please help

  • Import it in your document

    use File;

  • Hossein shojaeyan

    For laravel 5 ?

  • Lucas Gabriel

    noice. but how do i delete the file afterwards? many thx!

  • Hi!

    I have followed the steps and this doesn’t work, my file object on server y totally empty and dunno why.

    These are my lines of code:

    Route:

    Route::post(‘{zip}/{street}/photos’,’FlyersController@addPhoto’);

    Blade template with Dropzone:

    zip }}/{{ $flyer->street }}/photos” class=”dropzone”>
    {{ csrf_field() }}

    My controller

    public function addPhoto(Request $request,$zip,$street)
    {
    $input = Input::all();
    return Response::make($input, 200);
    }

    The problem is that the file object is empty, the response from the server is this:

    {“_token”:”pjWaWbuKzCXE3R8UrOnc9pepaHIKVIajzR1MJYOl”,”file”:{}}

    So file is created but is totally empty!!

    Any ideas? Thanks a lot!

  • angelor tuyo

    the post_upload doesn’t work. it returns a bunch of html codes.

More in Code Blog
whyLaravel
Why use Laravel?

What is Laravel? Why should any PHP developer care about it? A few days ago I had to present at...

Close