2

How can I integrate Dropzonejs file uploader library in wordpress front end just like the built in one and have the uploaded one available in my media library?

maksbd19
  • 3,785
  • 28
  • 37

3 Answers3

27

Dropzonejs is a very extensive javascript library that provides a lot of options to handle media uploading.

To integrate dropzonejs with wordpress the process is pretty straight forward. Assume the following piece of code is where you want to appear your uploader.

<div id="media-uploader" class="dropzone"></div>
<input type="hidden" name="media-ids" value="">

Having a class dropzone will automatically attach the dropzone event with the element. That will stop us from overriding default parameters. So we would like to disable the auto discover feature of the library.

// Disabling autoDiscover, otherwise Dropzone will try to attach twice.
Dropzone.autoDiscover = false;

Now we will use jQuery to bind our configuration with the element.

jQuery("#media-uploader").dropzone({
    url: dropParam.upload,
    acceptedFiles: 'image/*',
    success: function (file, response) {
        file.previewElement.classList.add("dz-success");
        file['attachment_id'] = response; // push the id for future reference
        var ids = jQuery('#media-ids').val() + ',' + response;
        jQuery('#media-ids').val(ids);
    },
    error: function (file, response) {
        file.previewElement.classList.add("dz-error");
    },
    // update the following section is for removing image from library
    addRemoveLinks: true,
    removedfile: function(file) {
        var attachment_id = file.attachment_id;        
        jQuery.ajax({
            type: 'POST',
            url: dropParam.delete,
            data: {
                media_id : attachment_id
            }
        });
        var _ref;
        return (_ref = file.previewElement) != null ? _ref.parentNode.removeChild(file.previewElement) : void 0;        
    }
});

In the code above what we have done is we attached dropzone with our element with some parameters-

  • url - location where we want to send our files to upload. I'll initialize the variable later.
  • acceptedFiles - since we are only interested in uploading images, we will limit the files to be attached only to images. You can find about more in the website of this library.
  • success - a callback that is fired when the file/image is uploaded successfully. It accepts two parameter the reference of the uploaded file itself and the response from the server. This is very important, here we stored the attachment id in our form. You can perform a validation here prior to store the id.
  • error - if the file failed to upload then you can perform any task here.
  • addRemoveLinks - add the remove file link below the preview panel, you can style it with your css.
  • removedfile - handles the operation while you click on the remove file link for an image in the preview panel. In this function we sent an ajax call to our server to remove the image from the library

Of course there are a lot of option available, but I found these are the most basic parameters I required to setup my drag-n-drop media uploader.

Now the most important thing is to decide about the file uploader url. You can have a custom file where you would want to process the operation. But I found another way.

From this question and the answer I found using admin-post.php file is pretty amazing.

Many people complained about this admin-post.php, so think sticking to the wp_ajax.php is the best option.

So I initialized the drophandler variable prior to my dropzone initialization as follows-

wp_enqueue_script('dropzone','path/to/dropzone', array('jquery'));
wp_enqueue_script('my-script','path/to/script',array('jquery','dropzone'));
$drop_param = array(
  'upload'=>admin_url( 'admin-ajax.php?action=handle_dropped_media' ),
  'delete'=>admin_url( 'admin-ajax.php?action=handle_deleted_media' ),
)
wp_localize_script('my-script','dropParam', $drop_param);

Now we are ready to send our images to the server. Here we will add some php code whether in the theme's function.php file or in our plugin file, but we need to be assured that it is loaded.

The following function will take care of the uploading the image and saving as an attachment in the library.

add_action( 'wp_ajax_handle_dropped_media', 'handle_dropped_media' );

// if you want to allow your visitors of your website to upload files, be cautious.
add_action( 'wp_ajax_nopriv_handle_dropped_media', 'handle_dropped_media' );



function handle_dropped_media() {
    status_header(200);

    $upload_dir = wp_upload_dir();
    $upload_path = $upload_dir['path'] . DIRECTORY_SEPARATOR;
    $num_files = count($_FILES['file']['tmp_name']);

    $newupload = 0;

    if ( !empty($_FILES) ) {
        $files = $_FILES;
        foreach($files as $file) {
            $newfile = array (
                    'name' => $file['name'],
                    'type' => $file['type'],
                    'tmp_name' => $file['tmp_name'],
                    'error' => $file['error'],
                    'size' => $file['size']
            );

            $_FILES = array('upload'=>$newfile);
            foreach($_FILES as $file => $array) {
                $newupload = media_handle_upload( $file, 0 );
            }
        }
    }

    echo $newupload;    
    die();
}

The following action take care of the deletion of the media element. Second parameter of wp_delete_attachment() function allows us to decide whether we want to trash the image or completely delete it. I wanted to delete it completely so passed true.

add_action( 'wp_ajax_handle_deleted_media', 'handle_deleted_media' );

function handle_deleted_media(){

    if( isset($_REQUEST['media_id']) ){
        $post_id = absint( $_REQUEST['media_id'] );

        $status = wp_delete_attachment($post_id, true);

        if( $status )
            echo json_encode(array('status' => 'OK'));
        else
            echo json_encode(array('status' => 'FAILED'));
    }

    die();
}

This will return the attachment_id in the response and we'll get it in the success function. In the media_handle_upload( $file, 0 ); I passed the reference of the file and a 0 because I didn't wanted to assign the media with any post yet (0 for no post, but if you want to assign then pass the post ID here. More reference in the codex.)

This is all for uploading media in wordpress.

Note: I haven't completed the removing uploaded file part. I'll complete this in a moment.

UPDATE

The post is updated. Now we can remove uploaded media elements from the uploader container. Thanks to this question and the answer I could figure out the actual process.

maksbd19
  • 3,785
  • 28
  • 37
  • Thanks for the post, very detailed explanation and closest to working example for what i need. But i have 2 problems, first it doesn't delete the files from website when you remove it from media list, second it doesn't work at all in Chrome. i get an error "Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience." – lonerunner Jun 29 '16 at 00:33
  • well, the "Synchronous XMLHttpRequest" error is for jquery's synchronous file transfer method. I believe there are tons of resources on resolving the error. And you need to hook your custom function in `delete_attachment` action to check whether that media item exist in your content's media list. If yes you need to remove it there. – maksbd19 Jun 29 '16 at 10:02
  • I am working on some changes to fit this to my needs, the XMLHttpRequest comes from wordpress ajax, so putting async: false solves the problem, But i found another problem now, the users who are not admins can't upload images, i don't know there is probably some kind of restriction that i need to look on. – lonerunner Jun 29 '16 at 17:17
  • For the permission I suggest you to look into `admin_post_{$action}` hook. You might made the restriction in the `handle_dropped_media` function. ref: https://codex.wordpress.org/Plugin_API/Action_Reference/admin_post_(action) – maksbd19 Jun 29 '16 at 20:57
  • I took some time tonight to take a look into debug console and i found what was causing the problem, i forgot that i made a code that is restricting access to anyone who is not admin into dashboard and admin pages. So i have to think about some kind of workaround for file uploads. To hook the function to front end. – lonerunner Jul 01 '16 at 02:07
  • As par the comment form @theBigK I'm changing `admin_post` to `wp_ajax` – maksbd19 Dec 23 '16 at 05:59
  • Where is wp_ajax.php located do you create this file? and wp_enqueue_script('my-script','path/to/script',array('jquery','dropzone')); where is this path go to? Where I place the "jQuery("#media-uploader").dropzone" code? – Tcmxc Jan 10 '18 at 18:11
  • am I missing something or should all references to "wp_ajax.php" actually be "admin-ajax.php" – Colm Troy Apr 18 '18 at 14:47
  • @maksbd19 What else were you going to add to the delete function? – zen_1991 Aug 14 '18 at 14:40
  • @zen_1991 this code above should work to delete media – maksbd19 Aug 14 '18 at 14:58
  • @maksbd19 the upload works correctly, the delete returns bad request. It is posting the correct ID – zen_1991 Aug 14 '18 at 15:00
  • @zen_1991 could you check if its getting along with the `handle_delete_media()` function? Or even the function is getting called at all? – maksbd19 Aug 14 '18 at 15:03
  • @maksbd19 function is being called and it is posting the correct id which matches the attachment id – zen_1991 Aug 14 '18 at 17:07
  • @zen_1991 So what is the problem with the bad request? – maksbd19 Aug 15 '18 at 10:15
  • 1
    @zen_1991 I had a typo in the `wp_deleted_media` – maksbd19 Aug 15 '18 at 10:19
  • Although this is an old post, I am grateful I found it! I am trying to get the attachments ids back in php to later attach to a post. How can I retrieve the ids of attachments in PHP? – scooterlord Jul 01 '20 at 17:56
  • 1
    @scooterlord after you upload a new image using the code above then `$newupload` will contain the attachment id of the newly uploaded image. you will get it in the response of the success callback – maksbd19 Jul 05 '20 at 20:34
1

Those who are having problems getting this to work for non-admin users; please use admin-ajax.php instead of admin-post.php.

I had faced a strange issue that admin-post.php would work for non-admin users on my local server; but my live server refused to let non-admins upload files. php would echo entire page instead of the echoed value.

I replaced admin-post.php with admin-ajax.php and uploads work super cool.

I hope this helps.

TheBigK
  • 233
  • 4
  • 16
-1

The solution added to this post is incorrect unless I've misunderstood the question. Basically the solution won't work for anyone who isn't logged in as an admin. It took me 30 minutes to work it out plus the solution for removing images doesn't delete it from the media library.

  • Thanks for your comment. As this is a comment not an answer actually this should go to the comment section. Any way I have updated the answer so that you can use this for allowing visitors of your website uploading files in your server, though I think this is not quite helpful. And finally what is wrong in your case? Files are removing fine in my case. Can you explain it a little so that I can modify mine? – maksbd19 Apr 16 '15 at 17:18
  • 1
    'delete'=>admin_url( 'wp_ajax.php?action=handle_deleted_media' ), needs to be changed to 'delete'=>admin_url( 'wp_ajax.php?action=handle_delete_media' ), – Tcmxc Jan 12 '18 at 19:55