How to Integrate Ajax File Upload in WordPress

Do you want to integrate Ajax file upload in WordPress? Sometimes, you need to perform the task of uploading a file through Ajax. In this article, we study how to upload files with jQuery and Ajax in WordPress. I’ll cover uploading both single and multiple files.

The main reason for uploading files through Ajax is it reduces loads on the server. This process does not require reloading the whole page which as a result saves extra calls to a server. Eventually, it saves the server bandwidth. This approach also gives a better user experience on your WordPress website.

Create HTML

For getting started, you need a form with the file input. Once the user browses a file on the client side, we will send the content of a file to the server side. On the server side, we collect the content of a file and store its copy under the wp-content/uploads directory. To create a file with the given content, I’ll use the wp_upload_bits method.

Having said that, let’s add the below HTML to your page template or anywhere you want.

<form enctype="multipart/form-data">
    <label>Choose File:</label>
    <input type="file" id="file" accept="image/*" />
</form>

I have given the id file on the file input to execute change events. The attribute accept=”image/*” will show only images in the file explorer. If you are looking for files other than images then remove this attribute.

Include JS File in WordPress Environment

To send the file on the server side, it is required to write JavaScript code. For this, I am going to create a custom.js into the theme directory and include it in the WordPress environment. This JavaScript file will handle:

  • Change event on file input
  • Collect the content of the file
  • Call the Ajax and post files data to the server

Write the below code inside the functions.php file which will include custom.js automatically on the front end.

function blog_scripts() {
    // Register the script
    wp_register_script( 'custom-script', get_stylesheet_directory_uri(). '/js/custom.js', array('jquery'), false, true );
 
    // Localize the script with new data
    $script_data_array = array(
        'ajaxurl' => admin_url( 'admin-ajax.php' ),
        'security' => wp_create_nonce( 'file_upload' ),
    );
    wp_localize_script( 'custom-script', 'blog', $script_data_array );
 
    // Enqueued script with localized data.
    wp_enqueue_script( 'custom-script' );
}
add_action('wp_enqueue_scripts', 'blog_scripts');

Look at the above code and you will notice 2 parameters passed to the custom.js file.

  • ajaxurl : In WordPress, all Ajax requests execute through the admin-ajax.php URL. Using our parameter, we are passing this URL to the JavaScript file.
  • security : With this parameter, I am passing a WordPress nonce to avoid CSRF attacks.

Write a JavaScript to Upload a File

We are ready with the HTML form and JS file. Now, we have to catch the change event, build the file object, and give an Ajax call. To achieve this, add the following code to the custom.js file.

jQuery(function($) {
    $('body').on('change', '#file', function() {
        $this = $(this);
        file_data = $(this).prop('files')[0];
        form_data = new FormData();
        form_data.append('file', file_data);
        form_data.append('action', 'file_upload');
        form_data.append('security', blog.security);
 
        $.ajax({
            url: blog.ajaxurl,
            type: 'POST',
            contentType: false,
            processData: false,
            data: form_data,
            success: function (response) {
                $this.val('');
                alert('File uploaded successfully.');
            }
        });
    });
});

Here, I am appending the file, action, and security arguments to the file object. We proceed with this file content on the server side to create a new file out of it. The values of action and security will be handled in the next step.

Upload File on Server

The value of the action argument is used to call the server-side PHP function. We need to pass this value to the wp_ajax actions as follows.

add_action('wp_ajax_file_upload', 'file_upload_callback');
add_action('wp_ajax_nopriv_file_upload', 'file_upload_callback');

You should add the above code to the functions.php file. To the wp_ajax and wp_ajax_nopriv, I appended the action’s value which is file_upload. The wp_ajax_{action} fires Ajax action. The second parameter file_upload_callback is the callback method which will have actual code for server-side file uploading.

Note: You don’t need to write the wp_ajax_nopriv action if you are adding this functionality on the backend. This action is required only for front-end users.

function file_upload_callback() {
    check_ajax_referer('file_upload', 'security');
    $arr_img_ext = array('image/png', 'image/jpeg', 'image/jpg', 'image/gif');
    if (in_array($_FILES['file']['type'], $arr_img_ext)) {
        $upload = wp_upload_bits($_FILES["file"]["name"], null, file_get_contents($_FILES["file"]["tmp_name"]));
        //$upload['url'] will gives you uploaded file path
    }
    wp_die();
}

The very first statement checks for security nonce and executes a code only if the nonce is valid. When you run this code, your file should be uploaded to the wp-content/uploads/ folder. You will find your file in the current month folder of the uploads directory.

Note: If you want to move your files to a custom directory then refer to our article – uploading files programmatically in WordPress.

Upload Multiple Files

Similar to a single file you would like to upload multiple files through Ajax. With a few changes in the previous code, you can easily achieve it.

First, add multiple attribute to the file input. This allows the user to browse multiple files at a time.

<form enctype="multipart/form-data">
    <label>Choose File:</label>
    <input type="file" id="file" accept="image/*" multiple />
</form>

On the JavaScript end, we will access these multiple files, loop through them, and build a final file object.

custom.js

jQuery(function($) {    
    $('body').on('change', '#file', function() {
        $this = $(this);
        file_obj = $this.prop('files');
        form_data = new FormData();
        for(i=0; i<file_obj.length; i++) {
            form_data.append('file[]', file_obj[i]);
        }
        form_data.append('action', 'file_upload');
        form_data.append('security', blog.security);
 
        $.ajax({
            url: blog.ajaxurl,
            type: 'POST',
            contentType: false,
            processData: false,
            data: form_data,
            success: function (response) {
                $this.val('');
                alert('File(s) uploaded successfully.');
            }
        });
    });
});

Finally, in the Ajax callback function, loop through the file array and upload each file on a server.

function file_upload_callback() {
    check_ajax_referer('file_upload', 'security');
    $arr_img_ext = array('image/png', 'image/jpeg', 'image/jpg', 'image/gif');
    for($i = 0; $i < count($_FILES['file']['name']); $i++) {
        if (in_array($_FILES['file']['type'][$i], $arr_img_ext)) {
            $upload = wp_upload_bits($_FILES['file']['name'][$i], null, file_get_contents($_FILES['file']['tmp_name'][$i]));
            //$upload['url'] will gives you uploaded file path
        }
    }
    wp_die();
}

I hope you understand the Ajax file upload in WordPress. This tutorial mainly focuses on uploading images. However, by removing references to images, you can upload any other file formats through this code.

If you liked this article, then please subscribe to our YouTube Channel for video tutorials.

21 thoughts on “How to Integrate Ajax File Upload in WordPress

  1. Scripts works well!!

    Do you know how to handle duplicate file upload? How to create a unique name before it uploaded?
    I was thinking to use wp_unique_filename but cannot get the file path before the file is uploaded.

    1. Append a unique string next to the file name. Something like uniqid().’_’.$_FILES[‘file’][‘name’]

  2. It worked just fine! But the issue is images are uploading to the current folder but not showing in the media library.

  3. AJAX calls in WP are not working with contentType: false or processData: false. I never managed to get it working like this.

  4. how to upload multiple file

    i’m use

    [code]
    var number = document.getElementById(‘file’);
    for (var i = 0; i < number; i++) {
    //var ‘file_data_’+i = $(this).prop(‘files’)[i];
    //window[‘file_data_’ + i ] = $(this).prop(‘files’)[i];
    var file_data = $(‘#file’).prop(‘files’)[0];

    }
    [/code]

    but not working

  5. Finally, someone that understands the special nuances of WP and AJAX! I was so close before this article, but couldn’t figure out how to pass my ‘action’… Didn’t think to put it inside the FormData… This line was the winner: form_data.append(‘action’, ‘file_upload’); THANK YOU

    1. Another way to do this is via HTML: input name=”action” type=”hidden” value=”action_name”
      which will include the action in the form data

Leave a Reply

Your email address will not be published. Required fields are marked *