如何在WooCommerce结账页面实现多文件上传功能
如何在WooCommerce结账页面实现多文件上传功能
嗨,看起来你已经基于@LoicTheAztec的代码搞定了单文件上传,要改成多文件上传其实只需要对现有代码做几处关键调整就行,我一步步给你说怎么改:
1. 调整结账页面的文件上传字段
首先要让前端的文件输入框支持多文件选择,给字段加上multiple属性就行:
add_action( 'woocommerce_after_order_notes', 'add_custom_checkout_field' ); function add_custom_checkout_field($checkout) { echo '<div class="woocommerce-additional-fields__field-wrapper">'; woocommerce_form_field('certificate', array( 'type' => 'file', 'class' => array('form-row-wide'), 'label' => __('文件', 'woocommerce'), 'required' => false, 'max_size' => '2048', // 单文件最大2MB 'accept' => '.pdf,.doc,.docx,.rtf,.txt', 'custom_attributes' => array( 'multiple' => 'multiple' // 开启多文件选择 ) ), ''); echo '</div>'; }
2. 更新JS文件处理多文件上传逻辑
修改你的checkout_upload.js,让它能批量处理选中的多个文件,通过AJAX上传到服务器:
jQuery(document).ready(function($) { // 监听文件选择事件 $('input[name="certificate"]').on('change', function() { const formData = new FormData(); const files = this.files; // 把所有选中的文件加入FormData for (let i = 0; i < files.length; i++) { formData.append('checkout_upload[]', files[i]); } formData.append('action', 'upload_checkout_files'); formData.append('security', wc_checkout_params.security); // 发起AJAX上传请求 $.ajax({ url: wc_checkout_params.ajax_url, type: 'POST', data: formData, contentType: false, processData: false, success: function(response) { if (response.success) { // 把多文件信息存入WooCommerce会话 wc_session.set('checkout_upload', response.data); } else { alert('文件上传失败:' + response.data); } }, error: function() { alert('网络错误,请重试文件上传'); } }); }); });
3. 新增AJAX后端处理函数(接收多文件)
在子主题的functions.php里添加处理多文件上传的AJAX函数,把每个文件保存到服务器并记录信息:
// 注册AJAX处理函数(登录/未登录用户都支持) add_action('wp_ajax_upload_checkout_files', 'handle_multiple_checkout_file_upload'); add_action('wp_ajax_nopriv_upload_checkout_files', 'handle_multiple_checkout_file_upload'); function handle_multiple_checkout_file_upload() { // 验证请求安全性 check_ajax_referer('wc_checkout', 'security'); $uploaded_files = []; $upload_dir = wp_upload_dir(); if (!empty($_FILES['checkout_upload']['name'])) { // 遍历所有上传的文件 foreach ($_FILES['checkout_upload']['name'] as $key => $file_name) { $file_tmp = $_FILES['checkout_upload']['tmp_name'][$key]; $file_size = $_FILES['checkout_upload']['size'][$key]; $file_error = $_FILES['checkout_upload']['error'][$key]; // 检查文件是否上传成功 if ($file_error === UPLOAD_ERR_OK) { // 生成唯一文件名避免覆盖 $unique_name = wp_unique_filename($upload_dir['path'], $file_name); $upload_path = $upload_dir['path'] . '/' . $unique_name; // 移动文件到WordPress上传目录 if (move_uploaded_file($file_tmp, $upload_path)) { $file_url = $upload_dir['url'] . '/' . $unique_name; // 记录文件原始名称和访问URL $uploaded_files[] = [ 'file_name' => $file_name, 'file_url' => $file_url ]; } } } } if (!empty($uploaded_files)) { WC()->session->set('checkout_upload', $uploaded_files); wp_send_json_success($uploaded_files); } else { wp_send_json_error('未检测到有效上传文件'); } }
4. 修改订单元数据保存逻辑
把多文件信息保存到订单的元数据里,这里我们把元数据键名改成复数更贴合场景:
add_action( 'woocommerce_checkout_create_order', 'save_checkout_uploaded_files', 10, 2 ); function save_checkout_uploaded_files( $order, $data ){ if( $checkout_uploads = WC()->session->get('checkout_upload') ) { $order->update_meta_data( '_checkout_uploads', $checkout_uploads ); } // 上传完成后清空会话中的临时数据 WC()->session->__unset('checkout_upload'); }
5. 调整各场景的文件显示逻辑
后台订单页面显示多文件
add_action('woocommerce_admin_order_data_after_billing_address', 'display_uploaded_files_in_admin_orders'); function display_uploaded_files_in_admin_orders( $order ){ if( $checkout_uploads = $order->get_meta( '_checkout_uploads' ) ) { echo '<p><strong>客户上传的文件:</strong><br>'; foreach( $checkout_uploads as $file ) { echo '<a href="' . esc_url($file['file_url']) . '" target="_blank">' . esc_html($file['file_name']) . '</a><br>'; } echo '</p>'; } }
订单感谢页面显示多文件
add_action('woocommerce_order_details_after_order_table', 'display_uploaded_files_in_thankyou'); function display_uploaded_files_in_thankyou ( $order ){ if( $checkout_uploads = $order->get_meta( '_checkout_uploads' ) ) { echo '<p><strong>你上传的文件:</strong><br>'; foreach( $checkout_uploads as $file ) { echo '<a href="' . esc_url($file['file_url']) . '" target="_blank">' . esc_html($file['file_name']) . '</a><br>'; } echo '</p>'; } }
订单邮件中显示多文件
add_action('woocommerce_email_customer_details', 'display_uploaded_files_in_email'); function display_uploaded_files_in_email ( $order ){ if( $checkout_uploads = $order->get_meta( '_checkout_uploads' ) ) { echo '<p><strong>上传的文件:</strong><br>'; foreach( $checkout_uploads as $file ) { echo '<a href="' . esc_url($file['file_url']) . '" target="_blank">' . esc_html($file['file_name']) . '</a><br>'; } echo '</p>'; } }
最后:确保JS文件正确加载
在functions.php里添加JS文件的注册逻辑,确保只在结账页面加载:
add_action('wp_enqueue_scripts', 'enqueue_checkout_upload_script'); function enqueue_checkout_upload_script() { // 仅在结账页面(非订单完成等端点)加载脚本 if (is_checkout() && !is_wc_endpoint_url()) { wp_enqueue_script( 'checkout-upload', get_stylesheet_directory_uri() . '/checkout_upload.js', array('jquery'), '1.0', true ); // 传递必要的全局参数给JS wp_localize_script('checkout-upload', 'wc_checkout_params', array( 'ajax_url' => admin_url('admin-ajax.php'), 'security' => wp_create_nonce('wc_checkout') )); } }
额外注意事项
- 请确保服务器的PHP配置支持多文件上传:调整
php.ini中的upload_max_filesize、post_max_size、max_file_uploads参数,避免因限制导致上传失败; - 每个文件的大小仍受你设置的
max_size(2MB)限制,若需要调整可修改字段参数; - 所有输出的链接都用了
esc_url和esc_html进行安全转义,避免XSS风险。
这样改完之后,你的WooCommerce结账页面就能完美支持多文件上传啦~
内容来源于stack exchange
相关产品推荐
相关产品推荐

