I want to have AJAX image upload on front-end form and can't figure out where it goes wrong.

HTML form for image upload

<form id="thumbnail_upload" method="post" action="#" enctype="multipart/form-data" >
  <input type="file" name="thumbnail" id="thumbnail">
  <input type='hidden' value='<?php wp_create_nonce( 'upload_thumb' ); ?>' name='_nonce' />
  <input type="hidden" name="action" id="action" value="my_upload_action">
<div id="output1"></div>

    jQuery(document).ready( function($) {
        var ajaxurl = '<?php echo admin_url('admin-ajax.php'); ?>';
        var options = { 
            target:        '#output1',      // target element(s) to be updated with server response 
            beforeSubmit:  showRequest,     // pre-submit callback 
            success:       showResponse,    // post-submit callback 
            url:    ajaxurl                 // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php     

            // bind form using 'ajaxForm'

        function showRequest(formData, jqForm, options) {
            //do extra stuff before submit like disable the submit button
        function showResponse(responseText, statusText, xhr, $form)  {
            //do extra stuff after submit


Here is PHP to handle image upload with media_handle_upload

// Enqueue jquery form
function load_jform() {
    wp_enqueue_script( 'jquery-form' ); 
add_action( 'wp_enqueue_scripts', 'load_jform' );

//hook the Ajax call
//for logged-in users
add_action('wp_ajax_my_upload_action', 'my_ajax_upload');

function my_ajax_upload(){
//simple Security check

//get POST data
    $post_id = 0;

//require the needed files
    require_once(ABSPATH . "wp-admin" . '/includes/image.php');
    require_once(ABSPATH . "wp-admin" . '/includes/file.php');
    require_once(ABSPATH . "wp-admin" . '/includes/media.php');

//then loop over the files that were sent and store them using  media_handle_upload();

    if ($_FILES) {
        foreach ($_FILES as $file => $array) {
            if ($_FILES[$file]['error'] !== UPLOAD_ERR_OK) {
                echo "upload error : " . $_FILES[$file]['error'];
            $attach_id = media_handle_upload( $file, $post_id );
//and if you want to set that image as Post  then use:

  echo "uploaded the new Thumbnail";

I actually don't need a foreach loop to upload multiple images cause it will only we one featured image but can't figure out how to change it properly.

With these code it give me just 0 on #output1 and I'm not sure where or how to debug this.

1 Answer 1


From my experience if an ajax call in wordpress returns 0, it means that ajax can't find the related php function, so check three times that the function you point to in 'add_action', function name and the action of your form do match.

I usually include an action attribute in the ajaxSubmit options as well, maybe it solves your problem. Just add action : 'my_ajax_upload' to the options array.

Since you have If you get -1 instead of 0, it means that the nonce check (check_ajax_referer($nonce)) failed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.