WooCommerce结账页添加文件上传字段失败求助
WooCommerce结账页文件上传字段不显示的解决方法
问题根源
WooCommerce的woocommerce_checkout_fields过滤器不支持直接添加type => 'file'的字段,同时默认结账表单没有设置enctype="multipart/form-data"属性,这两个原因导致你添加的文件上传字段无法显示,且就算显示也无法正常上传文件。
以下是修正后的完整代码,包含文本字段+文件上传字段的正确实现:
// 1. 修改结账表单编码,支持文件上传 add_action( 'woocommerce_checkout_init', 'enable_checkout_file_upload' ); function enable_checkout_file_upload() { add_filter( 'woocommerce_checkout_form_tag', function( $tag ) { return str_replace( 'method="post"', 'method="post" enctype="multipart/form-data"', $tag ); }); } // 2. 添加文本字段(保留原有正常代码) add_filter( 'woocommerce_checkout_fields', 'add_custom_text_checkout_fields' ); function add_custom_text_checkout_fields( $fields ) { $fields['billing']['video_title'] = array( 'type' => 'text', 'class' => array( 'form-row-wide' ), 'label' => __( '视频标题' ), 'placeholder' => __( '输入你的视频标题' ), 'required' => true, 'priority' => 1, ); $fields['billing']['video_subject'] = array( 'type' => 'text', 'class' => array( 'form-row-wide' ), 'label' => __( '视频主题' ), 'placeholder' => __( '输入你的视频主题' ), 'required' => true, 'priority' => 2, ); return $fields; } // 3. 渲染文件上传字段(用钩子直接输出HTML,替代原有无效方式) add_action( 'woocommerce_before_order_notes', 'add_custom_file_checkout_fields' ); function add_custom_file_checkout_fields( $checkout ) { echo '<div class="form-row form-row-wide">'; // 视频脚本上传字段 woocommerce_form_field( 'video_script', array( 'type' => 'file', 'class' => array('form-row-wide'), 'label' => __( '视频脚本' ), 'required' => false, 'description' => __( '支持PDF、DOCX格式,大小不超过5MB' ), ), $checkout->get_value( 'video_script' ) ); // 视频片头上传字段 woocommerce_form_field( 'video_intro', array( 'type' => 'file', 'class' => array('form-row-wide'), 'label' => __( '视频片头' ), 'required' => true, 'description' => __( '支持MP4、MOV格式,大小不超过20MB' ), ), $checkout->get_value( 'video_intro' ) ); echo '</div>'; } // 4. 验证字段(包含文件格式、大小检查) add_action( 'woocommerce_checkout_process', 'validate_custom_checkout_fields' ); function validate_custom_checkout_fields() { // 文本字段验证(WooCommerce会自动处理必填项,这里补充自定义逻辑) if ( empty( $_POST['video_title'] ) ) { wc_add_notice( __( '请填写视频标题' ), 'error' ); } if ( empty( $_POST['video_subject'] ) ) { wc_add_notice( __( '请填写视频主题' ), 'error' ); } // 视频脚本文件验证 if ( isset( $_FILES['video_script'] ) && $_FILES['video_script']['error'] == 0 ) { $allowed_types = array('application/pdf', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'); $file_type = wp_check_filetype( $_FILES['video_script']['name'] ); $file_size = $_FILES['video_script']['size'] / 1024 / 1024; // 转换为MB if ( ! in_array( $file_type['type'], $allowed_types ) ) { wc_add_notice( __( '视频脚本仅支持PDF、DOCX格式' ), 'error' ); } if ( $file_size > 5 ) { wc_add_notice( __( '视频脚本大小不能超过5MB' ), 'error' ); } } // 视频片头文件验证 if ( isset( $_FILES['video_intro'] ) ) { if ( $_FILES['video_intro']['error'] == 4 ) { // 未上传文件 wc_add_notice( __( '请上传视频片头' ), 'error' ); } else { $allowed_types = array('video/mp4', 'video/quicktime'); $file_type = wp_check_filetype( $_FILES['video_intro']['name'] ); $file_size = $_FILES['video_intro']['size'] / 1024 / 1024; if ( ! in_array( $file_type['type'], $allowed_types ) ) { wc_add_notice( __( '视频片头仅支持MP4、MOV格式' ), 'error' ); } if ( $file_size > 20 ) { wc_add_notice( __( '视频片头大小不能超过20MB' ), 'error' ); } } } } // 5. 保存字段数据到订单元 add_action( 'woocommerce_checkout_create_order', 'save_custom_checkout_fields_to_order' ); function save_custom_checkout_fields_to_order( $order ) { // 保存文本字段 if ( isset( $_POST['video_title'] ) ) { $order->update_meta_data( '_video_title', sanitize_text_field( $_POST['video_title'] ) ); } if ( isset( $_POST['video_subject'] ) ) { $order->update_meta_data( '_video_subject', sanitize_text_field( $_POST['video_subject'] ) ); } // 保存视频脚本文件 if ( isset( $_FILES['video_script'] ) && $_FILES['video_script']['error'] == 0 ) { $upload = wp_handle_upload( $_FILES['video_script'], array( 'test_form' => false ) ); if ( ! empty( $upload['error'] ) ) { wc_add_notice( __( '视频脚本上传失败:' . $upload['error'] ), 'error' ); } else { $order->update_meta_data( '_video_script_url', $upload['url'] ); $order->update_meta_data( '_video_script_path', $upload['file'] ); } } // 保存视频片头文件 if ( isset( $_FILES['video_intro'] ) && $_FILES['video_intro']['error'] == 0 ) { $upload = wp_handle_upload( $_FILES['video_intro'], array( 'test_form' => false ) ); if ( ! empty( $upload['error'] ) ) { wc_add_notice( __( '视频片头上传失败:' . $upload['error'] ), 'error' ); } else { $order->update_meta_data( '_video_intro_url', $upload['url'] ); $order->update_meta_data( '_video_intro_path', $upload['file'] ); } } } // 可选:在订单后台显示上传的文件链接 add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_custom_fields_in_admin_order' ); function display_custom_fields_in_admin_order( $order ) { echo '<div class="address">'; echo '<p><strong>' . __( '视频标题' ) . ':</strong> ' . $order->get_meta( '_video_title' ) . '</p>'; echo '<p><strong>' . __( '视频主题' ) . ':</strong> ' . $order->get_meta( '_video_subject' ) . '</p>'; $script_url = $order->get_meta( '_video_script_url' ); if ( $script_url ) { echo '<p><strong>' . __( '视频脚本' ) . ':</strong> <a href="' . esc_url( $script_url ) . '" target="_blank">点击下载</a></p>'; } $intro_url = $order->get_meta( '_video_intro_url' ); if ( $intro_url ) { echo '<p><strong>' . __( '视频片头' ) . ':</strong> <a href="' . esc_url( $intro_url ) . '" target="_blank">点击下载</a></p>'; } echo '</div>'; }
关键修改说明
- 添加表单编码:通过
woocommerce_checkout_init钩子修改结账表单的enctype属性,确保表单能接收文件数据。 - 单独渲染文件字段:使用
woocommerce_before_order_notes钩子,调用woocommerce_form_field直接输出文件上传控件,绕过woocommerce_checkout_fields的限制。 - 增强文件验证:增加了文件类型和大小的检查,避免无效文件上传。
- 规范元数据存储:订单元数据键使用下划线开头(如
_video_title),标记为私有元数据,不会在前台显示。 - 后台显示优化:添加了后台订单页面的字段展示,方便管理员查看和下载上传的文件。
内容的提问来源于stack exchange,提问作者Bent
相关产品推荐
相关产品推荐

