[英]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);
}
}
提交表单时,帖子与元键和元值一起创建,没有任何戏剧性,但文件附件不起作用。 我究竟做错了什么?
文件 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;
});
需要设置contentType
和processData
属性以防止 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.