dongliyan9190
2018-04-10 22:02
浏览 88

使用Ajax提交文件上传的Wordpress表单

I am trying to create form and submitting this with ajax. So the page wont reload. I don't have a lot of experience with ajax and I am trying to find as much information as I can.

Right now in my code I can sbmit form without reloading. But I have a field for uploading files. I know It is a bit different to do this and I also found some examples but so far no luck. For example Ajax file upload in Wordpress - can't pass FormData

Right now I have My Ajax code like this:

Ajax

(function($) {

jQuery(document).ready(function() {

    // when user submits the form
    jQuery(document).on('submit', '.form-assignment', function(event) {

        var error_elm = jQuery('.ajax-error');
        var response_elm = jQuery('.ajax-response')
       // var widgetId = grecaptcha.reset(container);
        error_elm.html('');
        response_elm.html('');

        // prevent form submission
        event.preventDefault();

        var form_elm = jQuery(this);

        var url = form_elm.data('url');
        var action = form_elm.data('action');
        var form_data = new FormData();

        var data = {
            action: action,
            form_data : form_data
        };

        // add loading message
        response_elm.html('Loading...');

        jQuery.ajax({
            type : 'POST',
            url : url,
            data : data,
            processData: false,
            contentType: false,
            enctype: 'multipart/form-data',
            dataType : 'json',
            async : true
        }).success(function(response) {

            error_elm.html('');
            response_elm.html('');

            if(response.status !== 'success') {
                // something went wrong
                if(response.message) {
                    error_elm.html(response.message);
                    return;
                }

                // don't know ?
            }

            // success!!

            // log data
            console.log(response);

            // display data
            response_elm.html(response.message);
            $("#form-assignment").trigger("reset");
            grecaptcha.reset();
        }).error(function(response) {
            error_elm.html('');
            response_elm.html('');

            error_elm.html(response.statusText);
        });
    });

});



})( jQuery );

My form:

 <div class="ajax-error" style="color: red;"></div>
    <form class="form-assignment" name="form_assignment" id="form-assignment"
          method="post" enctype="multipart/form-data"
          data-url="<?php echo esc_url( admin_url( 'admin-ajax.php' ) ) ?>" data-action="form_submit1">
          <label>name:</label>
          <input type="text" name="customer-field-text"pattern="[a-zA-Z0-9 ]+" placeholder="<?php echo $field->label ?>" size="40"/>
          <label>file upload</label>
           <input type="file"  name="customer-field-upload" id="customer-field-upload"
                           multiple="false"/>
    </form>

Right now this is how far I got. This is not my full form I have already added nonce and other required settings for sequrity. When I check input file It keep displaying error message that the field is empty.

My form handler

function handle_form_submission (){
global $wpdb;
$response = array(
    'status' => 'error',
    'message' => '',
);


parse_str($_POST['form_data'], $form_data);

//global $error;
$error = new WP_Error();

    if (empty($_POST['customer-field-name'])  ) {
    $error->add('empty','Name is required.');
}

    if (empty($_POST['customer-field-upload']) && empty($_FILES["customer-field-upload"]["name"])) {
    $error->add('empty','select an file.');
}

if ( !empty( $error->get_error_codes() ) ) {
    $error_messages = $error->get_error_messages();

    $error = '';
    foreach($error_messages as $error_message) {
        $error .= '<p>'.$error_message.'</p>';
    }

    $response['message'] = $error;

    wp_send_json( $response );
    wp_die();
}
$name                 = sanitize_text_field( $form_data["customer-field-name"] );
$upload                 = sanitize_text_field( $form_data["customer-field-upload"] );


require_once( ABSPATH . 'wp-admin/includes/image.php' );
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/media.php' );

 media_handle_upload( 'customer_field_upload', $form_data['post_id'] );

}

    add_action( 'wp_ajax_form_submit1', 'handle_form_submission' );

    // ajax hook for non-logged-in users: wp_ajax_nopriv_{action}
    add_action( 'wp_ajax_nopriv_form_submit1', 'handle_form_submission' );

So My question is What can I do or add in my ajax or form handler to get file upload submit with Ajax working. Any suggestion, advice or some existing example that are familiar will be appreciated. I am practicing with WordPress and Ajax that is how far I got.

I have tried to use FormData but still no luck so far.

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • dongxie9448 2018-04-15 23:45
    已采纳

    Here is some tips to make work your provided form:

    Form:

    <div class="ajax-error" style="color: red;"></div>
    <form class="form-assignment" name="form_assignment" id="form-assignment" method="post" enctype="multipart/form-data"
          data-url="<?php echo esc_url(admin_url('admin-ajax.php')) ?>" data-action="form_submit1">
        <label>name:</label>
        <input type="text" name="customer-field-text" pattern="[a-zA-Z0-9 ]+" size="40"/>
        <label>file upload</label>
        <input type="file" name="customer-field-upload" id="customer-field-upload" multiple="false"/>
        <input type="submit" value="Submit" name="submit">
    </form>
    

    I removed placeholder="<?php echo $field->label ?>" from your text input, because it's coming from custom code, which you didn't provide.

    Ajax.js:

    jQuery(document).ready(function ($) {
        // when user submits the form
        jQuery(document).on('submit', '.form-assignment', function (event) {
    
            var error_elm = jQuery('.ajax-error');
            var response_elm = jQuery('.ajax-response');
            error_elm.html('');
            response_elm.html('');
    
            event.preventDefault();
    
            var form_elm = jQuery(this);
    
            var url = form_elm.data('url');
            var action = form_elm.data('action');
            var file = form_elm[0][1].files[0];
            var customer_field_text = form_elm[0][0].value;
            var form_data = new FormData();
            form_data.append('action', action);
            form_data.append('customer-field-upload', file);
            form_data.append('customer-field-name', customer_field_text);
    
            response_elm.html('Loading...');
    
            jQuery.ajax({
                type: 'POST',
                url: url,
                data: form_data,
                processData: false,
                contentType: false,
                cache: false
            }).success(function (response) {
    
                error_elm.html('');
                response_elm.html('');
    
                if (response.status !== 'success') {
                    // something went wrong
                    if (response.message) {
                        error_elm.html(response.message);
                        return;
                    }
    
                    // don't know ?
                }
    
                response_elm.html(response.message);
                $("#form-assignment").trigger("reset");
    
            }).error(function (response) {
                error_elm.html('');
                response_elm.html('');
    
                error_elm.html(response.statusText);
            });
        });
    
    });
    

    NOTE: You're using var form_elm = jQuery(this);, which returns object of jquery with all Form content. That's why I used it for accessing input information. Instead you can access to form inputs with their name, class, id, placeholder and etc.

    What changed:

    1. removed (function($) {} wrapper and instead used jQuery(document).ready(function ($) {});. This is just for note. There is no need to wrapp your jquery to have access to $.
    2. We're getting file and name from inputs with lines below:

      var file = form_elm[0][1].files[0];
      var customer_field_text = form_elm[0][0].value;
      
    3. We're adding action for WordPress and form inputs with their values into FormData:

      form_data.append('action', action);
      form_data.append('customer-field-upload', file);
      form_data.append('customer-field-name', customer_field_text);
      

      Here you can change the name of array we're sending. For ex., we will recieve file in the array with key customer-field-upload and can use it such way:

      $_FILES['customer-field-upload']
      
    4. async : true: this line we don't need. It's true by default. enctype: 'multipart/form-data', we don't need, too.
    5. data: form_data,: we are sending everything only using one form_data variable( FormData object ).

    PHP file:

    1. I didn't use add_action('wp_ajax_nopriv_form_submit1', 'handle_form_submission'); because there is nothing related to nonce in your provided code
    2. Your $_POST will contain:

      Array
      (
         [action] => form_submit1 //action, which we used to send and accept Ajax request
         [customer-field-name] => some input value in the name field
      )
      

      You can access to name input using $_POST['customer-field-name'].

    3. Your $_FILES will contain:

      Array
      (
          [customer-field-upload] => Array
              (
                  [name] => input file name
                  [type] => input file type
                  [tmp_name] => temp file
                  [error] => 0 
                  [size] => some size
              )
      
      )
      

      You can work with input file using $_FILES['customer-field-upload']


    EDIT: Appended functional to add all inputs with several lines of code:

    Form:

    <div class="ajax-error" style="color: red;"></div>
    <form class="form-assignment" name="form_assignment" id="form-assignment" method="post" enctype="multipart/form-data"
          data-url="<?php echo esc_url(admin_url('admin-ajax.php')) ?>" data-action="form_submit1">
        <label for="customer-field-text">name:</label>
        <input type="text" name="customer-field-text" id="customer-field-text" pattern="[a-zA-Z0-9 ]+" size="40"/>
        <label>file upload</label>
        <input type="file" name="customer-field-upload" id="customer-field-upload" multiple="false"/>
        <label for="select">select:</label>
        <select name="carlist" id="select">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
            <option value="4">4</option>
        </select>
        <label for="email">email: </label>
        <input type="text" name="email" id="email">
        <input type="submit" value="Submit" name="submit">
    </form>
    

    Ajax.js:

    jQuery(document).ready(function ($) {
        // when user submits the form
        jQuery(document).on('submit', '.form-assignment', function (event) {
    
            var error_elm = jQuery('.ajax-error');
            var response_elm = jQuery('.ajax-response');
            error_elm.html('');
            response_elm.html('');
    
            event.preventDefault();
    
            var form_elm = jQuery(this);
    
            var url = form_elm.data('url');
            var action = form_elm.data('action');
            var file_input_name = jQuery('#form-assignment').find('input[type=file]').attr('id');
            var form_data = new FormData();
    
            form_data.append('action', action);
    
            jQuery.each(jQuery(':input:not([type=submit]):not([type=file])', '#form-assignment' ), function(i, fileds){
                form_data.append(jQuery(fileds).attr('name'), jQuery(fileds).val());
            });
            jQuery.each(jQuery(':input:not([type=submit]):not([type=text]):not([type=select])', '#form-assignment' )[0].files, function(i, file){
                form_data.append(file_input_name, file);
            });
    
            response_elm.html('Loading...');
    
            jQuery.ajax({
                type: 'POST',
                url: url,
                data: form_data,
                processData: false,
                contentType: false,
                cache: false
            }).success(function (response) {
    
                error_elm.html('');
                response_elm.html('');
    
                if (response.status !== 'success') {
                    // something went wrong
                    if (response.message) {
                        error_elm.html(response.message);
                        return;
                    }
    
                    // don't know ?
                }
    
                response_elm.html(response.message);
                $("#form-assignment").trigger("reset");
    
            }).error(function (response) {
                error_elm.html('');
                response_elm.html('');
    
                error_elm.html(response.statusText);
            });
        });
    
    });
    

    Here we used Jquery iterator to add several values from the loop into the FormData object. This is example and can be applied for checkboxes, textareas and etc.

    已采纳该答案
    打赏 评论
  • dongxu6418 2018-04-11 03:05

    You are missing enctype: 'multipart/form-data' and contentType: false to prevent jQuery from setting it to string. If that doesn't work, see this example and follow the same method

       jQuery.ajax({
            type : 'POST',
            enctype: 'multipart/form-data',
            url : url,
            data : data,
            async : true,
            processData: false,
            contentType: false,
        })
    
    打赏 评论
  • drcomwc134525 2018-04-11 04:39

    Your Jquery is missing the

    enctype: 'multipart/form-data'
    

    This is quite important when you are submitting the forms. This allows the form data to be sent without any conversions.

    jQuery.ajax({
                type : 'POST',
                url : url,
                data : data,
                enctype: 'multipart/form-data',
                dataType : 'json',
                async : true
            }).success(function(response) {
    
                error_elm.html('');
                response_elm.html('');
    
                if(response.status !== 'success') {
                    // something went wrong
                    if(response.message) {
                        error_elm.html(response.message);
                        return;
                    }
    
                    // don't know ?
                }
    
                // success!!
    
                // log data
                console.log(response);
    
                // display data
                response_elm.html(response.message);
            }).error(function(response) {
                error_elm.html('');
                response_elm.html('');
    
                error_elm.html(response.statusText);
            });
        });
    
    打赏 评论

相关推荐 更多相似问题