Have you ever needed to offer your customers the possibility to upload a file before the payment of a product or service? And I don’t mean uploading files on the product page, that’s easy and there are many plugins that allow it, for customized products and things like that, but uploading files at checkout, such as an affiliation document, identity card or things like that, necessary for some reason.
And if I say that on the product page is easy, it is not only because there are plugins for it, but because the HTML fields needed to offer file uploads do not work on the checkout page, being a particularly sensitive page, and protected, with all logic.
Table of Contents
The code
The upload process must be done before all the payment fields are loaded, and via AJAX, something we can achieve with a code like the following:
/* Uploading files at checkout */
add_action( 'woocommerce_after_order_notes', 'wphelp_upload_file_checkout' );
function wphelp_upload_file_checkout() {
echo '<p class="form-row"><label for="appform">Identification document (PDF)<abbr class="required" title="required">*</abbr></label><span class="woocommerce-input-wrapper"><input type="file" id="appform" name="appform" accept=".pdf" required><input type="hidden" name="appform_field" /></span></p>';
wc_enqueue_js( "
$( '#appform' ).change( function() {
if ( this.files.length ) {
const file = this.files[0];
const formData = new FormData();
formData.append( 'appform', file );
$.ajax({
url: wc_checkout_params.ajax_url + '?action=appformupload',
type: 'POST',
data: formData,
contentType: false,
enctype: 'multipart/form-data',
processData: false,
success: function ( response ) {
$( 'input[name=\"appform_field\"]' ).val( response );
}
});
}
});
" );
}
add_action( 'wp_ajax_appformupload', 'wphelp_form_upload' );
add_action( 'wp_ajax_nopriv_appformupload', 'wphelp_form_upload' );
function wphelp_form_upload() {
global $wpdb;
$uploads_dir = wp_upload_dir();
if ( isset( $_FILES['appform'] ) ) {
if ( $upload = wp_upload_bits( $_FILES['appform']['name'], null, file_get_contents( $_FILES['appform']['tmp_name'] ) ) ) {
echo $upload['url'];
}
}
die;
}
add_action( 'woocommerce_checkout_process', 'wphelp_validate_upload_field' );
function wphelp_validate_upload_field() {
if ( empty( $_POST['appform_field'] ) ) {
wc_add_notice( 'Upload your file', 'error' );
}
}
add_action( 'woocommerce_checkout_update_order_meta', 'wphelp_save_upload_field' );
function wphelp_save_upload_field( $order_id ) {
if ( ! empty( $_POST['appform_field'] ) ) {
update_post_meta( $order_id, '_application', $_POST['appform_field'] );
}
}
add_action( 'woocommerce_admin_order_data_after_billing_address', 'wphelp_show_upload_field', 10, 1 );
function wphelp_show_upload_field( $order ) {
$order_id = $order->get_id();
if ( get_post_meta( $order_id, '_application', true ) ) echo '<p><strong>Upload PDF:</strong> <a href="' . get_post_meta( $order_id, '_application', true ) . '" target="_blank">' . get_post_meta( $order_id, '_application', true ) . '</a></p>';
}
add_action( 'woocommerce_email_after_order_table', 'wphelp_show_email_upload_field', 20, 4 );
function wphelp_show_email_upload_field( $order, $sent_to_admin, $plain_text, $email ) {
if ( $sent_to_admin && get_post_meta( $order->get_id(), '_application', true ) ) echo '<p><strong>PDF file:</strong> ' . get_post_meta( $order->get_id(), '_application', true ) . '</p>';
}
Code language: PHP (php)
What does the code that allows uploading files at checkout do?
This example code adds a required file upload field (class="required"
) to the end of the standard WooCommerce fields, which must be a PDF file type (accept=".pdf"
) and uploads it to the current upload directory ($uploads_dir = wp_upload_dir()
).
You can change texts or the allowed file type, of course.
Where should I add this code?
As it is an independent functionality of the theme you should not add the code to the functions.php file of the active theme, although it works (tested), you can choose some other way to add it, as I explained in this simple guide…
How and where to paste PHP, JS, CSS codes and functions you find around in WordPress
Does it work?
Of course, I have tested it in several WooCommerce installations, with several popular themes and adding the code as a function, plugin and snippet and it works perfectly, as the following before and after screenshots show.

