dongliyan9190 2018-04-10 22:02
浏览 92
已采纳

使用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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮