繁体   English   中英

使用 Ajax 在 WordPress 前端上传多个文件

[英]Uploading multiple files on WordPress front-end using Ajax

我有一个带有前端表单的自定义主题,用于使用 Ajax 创建帖子,除了文件上传之外它可以工作。

表格看起来像这样...

<form class="job-form" id="job-form" method="post" enctype="multipart/form-data">

    <input type="text" name="job_title" id="job_title" />
    <input type="text" name="job_description" id="job_description" />
    <input type="file" name="job_files[]" id="job_files" multiple="multiple"/>

    <button>Submit</button>
</form>

...而这个 JS...

$('#job-form').on('submit', function(e) {
    e.preventDefault();

    $.post( inputs.ajaxurl, {
        action : 'add_job',
        nonce : inputs.nonce,
        post : $(this).serialize()
    },
    function(response) {
        console.log(response);
        ResponseSuccess(response);
    }); 

    return false;

});

..和 PHP 将所有内容添加到数据库中:

add_action( 'wp_ajax_add_job', 'wp_ajax_add_job' );
add_action( 'wp_ajax_nopriv_add_job', 'add_job' );
function add_job() {

    $params = array();
    parse_str($_POST["post"], $params);

    if(isset($_POST["job-form"])) {

        $job_title          = sanitize_text_field($params['job_title']);
        $job_description    = sanitize_text_field($params['job_description']);

        $args = array(
            'post_title'    => $job_title,
            'post_status'   => 'publish',
            'post_type'     => 'jobs',
            'post_author'   => 1
        );
        
        $result     = wp_insert_post( $args );
        $post_id    = $result;
    
        add_post_meta( $post_id, "job_title" , $job_title);
        add_post_meta( $post_id, "job_description" , $job_description);

        /* If attachments were attached, upload them */
        if($_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');

            $files = $_FILES["job_files"];  
            foreach ($files['name'] as $key => $value) {            
                if ($files['name'][$key]) { 
                    $file = array( 
                        'name'      => $files['name'][$key],
                        'type'      => $files['type'][$key], 
                        'tmp_name'  => $files['tmp_name'][$key], 
                        'error'     => $files['error'][$key],
                        'size'      => $files['size'][$key]
                    ); 
                    $_FILES = array ("job_files" => $file); 
                    foreach ($_FILES as $file => $array) {              
                        $new_upload = media_handle_upload($file,$post_id); 
                    }
                } 
            }
        }

        ajaxStatus('job-created', __('Job created.', 'jobs-theme'), $post_id);
            
    }
}

提交表单时,帖子与元键和元值一起创建,没有任何戏剧性,但文件附件不起作用 我究竟做错了什么?

正如serialize的 jQuery 文档所解释的,

文件 select 元素中的数据未序列化。

原因是serialize将表单元素编码为application/x-www-form-urlencoded格式,该格式只能容纳纯文本字符串值,不能容纳文件上传。 为了能够上传文件,您必须以multipart/form-data格式提交整个表单。 实现它的一种方法是使用FormData object jQuery 不直接支持,但可以轻松容纳。

这是您的代码的最小修改以使其工作:

$('#job-form').on('submit', function(e) {
    e.preventDefault();

    // take the data from the form
    const formData = new FormData(this);
    // append further fields
    formData.append('action', 'add_job');
    formData.append('nonce', inputs.nonce);

    $.ajax( inputs.ajaxurl, {
        type: 'POST',
        data: formData,
        contentType: false, // prevent jQuery from using an incorrect Content-type header
        processData: false, // prevent jQuery from mangling the form data
        success: function(response) {
            console.log(response);
            ResponseSuccess(response);
        }
    }); 

    return false;
});

需要设置contentTypeprocessData属性以防止 jQuery 破坏数据并添加不正确的标题。

因为我必须修改实际提交的表单结构才能处理文件上传,所以也必须修改表单代码和接收者脚本,例如:

    <form class="job-form" id="job-form" method="post" enctype="multipart/form-data">

        <input type="text" name="post[job_title]" id="job_title" />
        <input type="text" name="post[job_description]" id="job_description" />
        <input type="file" name="job_files[]" id="job_files" multiple="multiple"/>

        <button>Submit</button>
    </form>

在接收脚本中:

    # ...
    function add_job() {

        $params = $_POST['post'];

        if(isset($_POST["job-form"])) {
    # ...

在这里,我利用了 PHP 的内置结构形式解析,其中名称为a[b]的字段生成关联的 arrays,可以在 PHP 端以$_POST['a']['b']的形式访问。

您需要重写您的 ajax 请求代码,如下所示。


var $form = $("#yourFormSelector");
$.ajax({
    type: 'post',
    url: 'url',
    data: new FormData($form[0]),
    contentType: false,
    processData: false,
    success: function(response) {
        //Your response handler code...
    }
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM