-1

I am using a code that adds a file upload field on the checkout page. How to add file upload to WooCommerce checkout? Many thanks to @LoicTheAztec for this code.

I have created the files checkout_uploads.php, checkout_upload.js and added the code to functions.php a child theme.

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'     => __('File', 'woocommerce'),
        'required'  => false,
        'max_size'  => '2048',
        'accept'    => '.pdf,.doc,.docx,.rtf,.txt',
    ), '');

    echo '</div>';
}

// Save the uploaded file URL and name
add_action( 'woocommerce_checkout_create_order', 'save_checkout_uploaded_file', 10, 2 );
function save_checkout_uploaded_file( $order, $data ){
    if( $checkout_upload = WC()->session->get('checkout_upload') ) {
        $order->update_meta_data( '_checkout_upload', $checkout_upload ); 
    }
    WC()->session->__unset('checkout_upload');
}

// Display the uploaded file in admin orders
add_action('woocommerce_admin_order_data_after_billing_address', 'display_uploaded_file_in_admin_orders');
function display_uploaded_file_in_admin_orders( $order ){
    if( $checkout_upload = $order->get_meta( '_checkout_upload' ) ) {
        printf( '<p>%s <br><a href="%s">%s</a></p>', 
            __("File Uploaded:", 'woocommerce'), 
            $checkout_upload['file_url'], 
            $checkout_upload['file_name'] 
        );
    }
}

// Display the uploaded file in thankyou page
add_action('woocommerce_order_details_after_order_table', 'display_uploaded_file_in_thankyou');
function display_uploaded_file_in_thankyou ( $order ){
    if( $checkout_upload = $order->get_meta( '_checkout_upload' ) ) {
        printf( '<p>%s <br><a href="%s">%s</a></p>', 
            __("File Uploaded:", 'woocommerce'), 
            $checkout_upload['file_url'], 
            $checkout_upload['file_name'] 
        );
    }
}

// Display the uploaded file in emails
add_action('woocommerce_email_customer_details', 'display_uploaded_file_in_email');
function display_uploaded_file_in_email ( $order ){
    if( $checkout_upload = $order->get_meta( '_checkout_upload' ) ) {
        printf( '<p>%s <a href="%s">%s</a></p>', 
            __("File Uploaded:", 'woocommerce'), 
            $checkout_upload['file_url'], 
            $checkout_upload['file_name'] 
        );
    }
}

Only one file can be uploaded at the moment. How can I upload multiple files at the same time? I will be glad of your help!

7
  • There is no need to hide behind your anonymity and put downvotes (-2 votes in 5 minutes). If you have something to say, speak openly. Commented Sep 1 at 20:26
  • what I reproach at your question was written in comments yesterday but I don't know why theses comments were deleted. Commented Sep 1 at 21:16
  • Then write your comment again, either remove your downvote. Commented Sep 2 at 6:20
  • I think you should add the "multiple" attribute to your input. You should add it to the array you are using in the "woocommerce_form_field" function. From what I remember you should add the following as a value in the array: custom_attributes=>array("multiple"), Commented Sep 2 at 7:23
  • Unfortunately 'custom_attributes' => array('multiple'), does not work. It seems to me that the source code of the file needs to be slightly modified checkout_uploads.php? Commented Sep 2 at 7:55

1 Answer 1

1

Something like that:

// 1. Display multiple upload file field
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'     => __('Files', 'woocommerce'),
        'required'  => false,
        'multiple'  => 'multiple',
        'name'      => 'certificate[]', // as array
        'accept'    => '.pdf,.doc,.docx,.rtf,.txt',
    ), '');
    echo '</div>';
}

// 2. Save multiple uploaded files URL and name to order meta
add_action( 'woocommerce_checkout_create_order', 'save_checkout_uploaded_files', 10, 2 );
function save_checkout_uploaded_files( $order, $data ){
    if( !empty($_FILES['certificate']['name'][0]) ) {
        $uploaded_files = array();

        foreach ($_FILES['certificate']['name'] as $key => $value) {
            if ($_FILES['certificate']['error'][$key] === UPLOAD_ERR_OK) {
                $file = array(
                    'name'     => $_FILES['certificate']['name'][$key],
                    'type'     => $_FILES['certificate']['type'][$key],
                    'tmp_name' => $_FILES['certificate']['tmp_name'][$key],
                    'error'    => $_FILES['certificate']['error'][$key],
                    'size'     => $_FILES['certificate']['size'][$key]
                );

                // Handle upload safely using WP functions
                $upload = wp_handle_upload($file, array('test_form' => false));

                if (!isset($upload['error'])) {
                    $uploaded_files[] = array(
                        'file_url'  => $upload['url'],
                        'file_name' => $file['name']
                    );
                }
            }
        }
        if (!empty($uploaded_files)) {
            $order->update_meta_data( '_checkout_upload', $uploaded_files );
        }
    }
}

// 3. Helper function to display uploaded files as links
function display_uploaded_files_list($files) {
    if (!empty($files) && is_array($files)) {
        echo '<p>' . __("Files Uploaded:", 'woocommerce') . '</p><ul>';
        foreach ($files as $file) {
            printf('<li><a href="%s" target="_blank" rel="noopener noreferrer">%s</a></li>', esc_url($file['file_url']), esc_html($file['file_name']));
        }
        echo '</ul>';
    }
}

// 4. Display uploaded files in admin order page
add_action('woocommerce_admin_order_data_after_billing_address', 'display_uploaded_files_in_admin_orders');
function display_uploaded_files_in_admin_orders( $order ) {
    $uploaded_files = $order->get_meta( '_checkout_upload' );
    display_uploaded_files_list($uploaded_files);
}

// 5. Display uploaded files on thank you page
add_action('woocommerce_order_details_after_order_table', 'display_uploaded_files_in_thankyou');
function display_uploaded_files_in_thankyou( $order ) {
    $uploaded_files = $order->get_meta( '_checkout_upload' );
    display_uploaded_files_list($uploaded_files);
}

// 6. Display uploaded files in WooCommerce emails
add_action('woocommerce_email_customer_details', 'display_uploaded_files_in_email');
function display_uploaded_files_in_email( $order ) {
    $uploaded_files = $order->get_meta( '_checkout_upload' );
    display_uploaded_files_list($uploaded_files);
}

____

WooCommerce’s woocommerce_form_field does not natively support the HTML5 multiple attribute for file inputs, and by default, it will use name="certificate" than name="certificate[]" so:

Render the file input with custom HTML:

add_action( 'woocommerce_after_order_notes', 'add_custom_checkout_field' );
function add_custom_checkout_field($checkout) {
    echo '<div class="woocommerce-additional-fields__field-wrapper">';
    echo '<p class="form-row form-row-wide">';
    echo '<label for="certificate">' . __('Files', 'woocommerce') . '</label>';
    echo '<input type="file" name="certificate[]" id="certificate" multiple accept=".pdf,.doc,.docx,.rtf,.txt" />';
    echo '</p></div>';
}

Handle multi-file upload in the WooCommerce order hook:

add_action( 'woocommerce_checkout_create_order', 'save_checkout_uploaded_files', 10, 2 );
function save_checkout_uploaded_files( $order, $data ){
    if( !empty($_FILES['certificate']['name'][0]) ) {
        $uploaded_files = array();

        foreach ($_FILES['certificate']['name'] as $i => $name) {
            if ($_FILES['certificate']['error'][$i] === UPLOAD_ERR_OK) {
                $file = array(
                    'name'     => $_FILES['certificate']['name'][$i],
                    'type'     => $_FILES['certificate']['type'][$i],
                    'tmp_name' => $_FILES['certificate']['tmp_name'][$i],
                    'error'    => $_FILES['certificate']['error'][$i],
                    'size'     => $_FILES['certificate']['size'][$i]
                );

                $upload = wp_handle_upload($file, array('test_form' => false));
                if (!isset($upload['error'])) {
                    $uploaded_files[] = array(
                        'file_url'  => $upload['url'],
                        'file_name' => $file['name']
                    );
                }
            }
        }
        if (!empty($uploaded_files)) {
            $order->update_meta_data( '_checkout_upload', $uploaded_files );
        }
    }
}

and display all uploaded files:

function display_uploaded_files_list($files) {
    if (!empty($files) && is_array($files)) {
        echo '<p>' . __("Files Uploaded:", 'woocommerce') . '</p><ul>';
        foreach ($files as $file) {
            printf('<li><a href="%s" target="_blank" rel="noopener noreferrer">%s</a></li>', esc_url($file['file_url']), esc_html($file['file_name']));
        }
        echo '</ul>';
    }
}

add_action('woocommerce_admin_order_data_after_billing_address', function($order) {
    $files = $order->get_meta('_checkout_upload');
    display_uploaded_files_list($files);
});

add_action('woocommerce_order_details_after_order_table', function($order) {
    $files = $order->get_meta('_checkout_upload');
    display_uploaded_files_list($files);
});

add_action('woocommerce_email_customer_details', function($order) {
    $files = $order->get_meta('_checkout_upload');
    display_uploaded_files_list($files);
});

____
edit 2 - this should work:

1: Add multiple file input field on checkout

Add this code to your theme’s functions.php or a custom plugin. It inserts a multiple file input after the order notes.

add_action( 'woocommerce_after_order_notes', 'add_custom_checkout_field' ); function add_custom_checkout_field( $checkout ) {
     echo '<div class="woocommerce-additional-fields__field-wrapper">';
     echo '<p class="form-row form-row-wide">';
     echo '<label for="certificate">' . __( 'Files', 'woocommerce' ) . '</label>';
     echo '<input type="file" name="certificate[]" id="certificate" multiple accept=".pdf,.doc,.docx,.rtf,.txt" />';
     echo '</p></div>'; 
} 
  • This creates a file input that allows selecting multiple files.

The input name certificate[] ensures files are submitted as an array.

2: Handle and save uploaded files to order meta

Add code to process uploaded files when the order is created.

add_action( 'woocommerce_checkout_create_order', 'save_checkout_uploaded_files', 20, 2 );
function save_checkout_uploaded_files( $order, $data ) {
    if ( ! empty( $_FILES['certificate']['name'][0] ) ) {
        $uploaded_files = [];
        foreach ( $_FILES['certificate']['name'] as $i => $name ) {
            if ( $_FILES['certificate']['error'][ $i ] === UPLOAD_ERR_OK ) {
                $file = [
                    'name'     => $_FILES['certificate']['name'][ $i ],
                    'type'     => $_FILES['certificate']['type'][ $i ],
                    'tmp_name' => $_FILES['certificate']['tmp_name'][ $i ],
                    'error'    => $_FILES['certificate']['error'][ $i ],
                    'size'     => $_FILES['certificate']['size'][ $i ],
                ];
                $upload = wp_handle_upload( $file, [ 'test_form' => false ] );
                if ( ! isset( $upload['error'] ) ) {
                    $uploaded_files[] = [
                        'file_url'  => $upload['url'],
                        'file_name' => $file['name'],
                    ];
                }
            }
        }
        if ( $uploaded_files ) {
            $order->update_meta_data( '_checkout_upload', $uploaded_files );
            $order->save();  // Save meta data
        }
    }
}
  • Loop through each uploaded file.

  • Use WordPress function wp_handle_upload to save files securely.

  • Save an array of file data (URL and name) in order meta _checkout_upload.

3: Display uploaded files list (helper function)

Create a reusable function to output uploaded file links.

function display_uploaded_files_list( $files ) {
    if ( ! empty( $files ) && is_array( $files ) ) {
        echo '<p>' . __( 'Files Uploaded:', 'woocommerce' ) . '</p><ul>';
        foreach ( $files as $file ) {
            printf(
                '<li><a href="%s" target="_blank" rel="noopener noreferrer">%s</a></li>',
                esc_url( $file['file_url'] ),
                esc_html( $file['file_name'] )
            );
        }
        echo '</ul>';
    }
}


4: Show uploaded files on the admin order details page

add_action( 'woocommerce_admin_order_data_after_billing_address', function( $order ) {
    $files = $order->get_meta( '_checkout_upload' );
    display_uploaded_files_list( $files );
} );

5: Show uploaded files on the Thank You page

add_action( 'woocommerce_order_details_after_order_table', function( $order ) {
    $files = $order->get_meta( '_checkout_upload' );
    display_uploaded_files_list( $files );
} );

6: Show uploaded files in WooCommerce order emails


add_action( 'woocommerce_email_customer_details', function( $order ) {
    $files = $order->get_meta( '_checkout_upload' );
    display_uploaded_files_list( $files );
} );

7: Test

Place a new order.

  • On checkout, select multiple files using the file input.

  • Complete the order.

  • Check in WordPress admin Orders page if files appear under billing address.

  • Review the Thank You page after checkout for uploaded files links.

  • Check WooCommerce order emails for file links.

Confirm your server PHP settings allow uploading files of your desired size (upload_max_filesize, post_max_size).

Clear any caches or object cache that may hide updated order meta.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks for the answer. Unfortunately, this code doesn't work for me. Only one file is uploaded. The link to the file is not shown on the order page, on the Thank You page, or in WooCommerce emails.
That could be becouse by default, woocommerce_form_field for 'file' does not produce an input with multiple or [] name. Please my edit of answer
Is the new code working for you? When I place an order, the files are uploaded to the 0001 folder of the site directory. But on the order page, on the Thank You page, and in WooCommerce emails, these files are not shown.
P.S. Can you help with this? I made a new bounty for you.
Made another edit. Check also that saving meta happens in woocommerce_checkout_create_order hook properly. You can add debugging code to dump the saved meta immediately after saving, or view order meta in database.
When uploading multiple files, only the first file is uploaded to the site directory. In the database, this file is only in the "wp_woocommerce_sessions" table. The file is also not shown on the order page, on the Thank You page, and in emails.
Does this code work for you? Maybe still need to fix the files checkout_uploads.php and checkout_upload.js ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.