WordPress中使用admin-ajax.php上传图片遇400错误请求问题排查
问题背景
在WordPress中尝试通过Ajax上传imageMaker生成的图片,多次尝试均返回400 Bad Request,怀疑upload_file_callback函数未被调用。已尝试多种传递图片的方式(直接传图片、Image类形式、base64编码)均无效。测试地址:https://bespokelazienki.pl/41736-2/
相关代码
PHP插件代码
<?php /* Plugin Name: Sizer Description: Sizer Version: 1.00 */ function upload_file_callback(){ if (isset($_POST['upload_file_callback'])){ echo'ok'; } else{ echo 'bad'; } } add_action('wp_ajax_nopriv_upload_file', 'upload_file_callback'); add_action( 'wp_ajax_upload_file', 'upload_file_callback' ); ?>
JS代码片段
onGenerate: function(data, formData){ var ajax_url = 'https://bespokelazienki.pl/wp-admin/admin-ajax.php'; var image = new Image(); image.src = data["amm_canvas"]; image.name = "123.png"; var q = '<?php echo wp_create_nonce('uploadingFile'); ?>'; var fd = new FormData(); fd.append("security", q); fd.append("file",dataURLtoFile(data["amm_canvas"], 'filename.png')); fd.append("action", "upload_file_callback"); for (var pair of fd.entries()) { console.log(pair[0]+ ', ' + pair[1]); } $.ajax({ url:ajax_url, type:"POST", processData: false, contentType: false, enctype: "multipart/form-data", data: fd, success : function( response ){ var returnedData = JSON.parse(response); if(returnedData.code == 200){ alert('File uploaded!'); }else{ alert(returnedData.msg); } },
解决思路
修正Action钩子匹配
PHP代码注册的Ajax action是upload_file(对应wp_ajax_upload_file和wp_ajax_nopriv_upload_file),但JS里传递的action是upload_file_callback,两者不匹配导致钩子无法触发。把JS里的fd.append("action", "upload_file_callback");改为fd.append("action", "upload_file");。添加Nonce校验
PHP回调里未验证nonce,这是WordPress Ajax安全要求的必要步骤,会直接导致400错误。在upload_file_callback开头添加校验:if (!wp_verify_nonce($_POST['security'], 'uploadingFile')) { wp_send_json_error(['msg' => '无效的安全验证']); }同时检查前端页面源码,确认
q变量输出的是有效nonce值——如果JS是独立文件而非PHP模板,<?php echo wp_create_nonce('uploadingFile'); ?>不会被解析,需要通过wp_localize_script传递nonce。修正文件检查逻辑
PHP回调里判断的$_POST['upload_file_callback']从未在JS中传递,应改为检查上传的文件:isset($_FILES['file']),同时补充文件上传处理逻辑,比如用wp_handle_upload完成存储。统一响应格式
JS里尝试解析JSON响应,但PHP当前仅输出字符串,会导致JSON.parse报错。PHP改用wp_send_json_success或wp_send_json_error返回标准JSON:function upload_file_callback(){ if (!wp_verify_nonce($_POST['security'], 'uploadingFile')) { wp_send_json_error(['msg' => '无效的安全验证']); } if (isset($_FILES['file'])) { // 此处添加wp_handle_upload等文件处理逻辑 wp_send_json_success(['code' => 200, 'msg' => '文件上传成功']); } else { wp_send_json_error(['msg' => '未检测到上传文件']); } }排查权限与跨域
若测试时未登录,确认wp_ajax_nopriv_upload_file钩子已正确注册;若登录状态,检查当前用户是否有上传文件权限。同时确认前端与admin-ajax.php为同域,避免跨域限制。
内容的提问来源于stack exchange,提问作者Patryk Organiściak

