You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>';
}

关键修改说明

  1. 添加表单编码:通过woocommerce_checkout_init钩子修改结账表单的enctype属性,确保表单能接收文件数据。
  2. 单独渲染文件字段:使用woocommerce_before_order_notes钩子,调用woocommerce_form_field直接输出文件上传控件,绕过woocommerce_checkout_fields的限制。
  3. 增强文件验证:增加了文件类型和大小的检查,避免无效文件上传。
  4. 规范元数据存储:订单元数据键使用下划线开头(如_video_title),标记为私有元数据,不会在前台显示。
  5. 后台显示优化:添加了后台订单页面的字段展示,方便管理员查看和下载上传的文件。

内容的提问来源于stack exchange,提问作者Bent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 12:25:05