How to Create File Uploader on Checkout Page

In this tutorial I will show you step by step how to add a file uploader field to WooCommerce checkout page without any plugins.

I am going to use images as an example:

WooCommerce checkout page with file uploader field
Here is how the WooCommerce checkout page looks like with the image attached. I am using Storefront theme here and by the way you might notice that we don’t have a lot of billing fields here, read how to remove them easily.

First, Decide Where Exactly to Display the Uploader Field

Out goal for now is just to display the field HTML and we are going to use a WooCommerce hook for that. If you would like to display the field exactly like on the screenshot above, you can use woocommerce_after_checkout_billing_form, but there are more hooks available.

<?php
add_action( 'woocommerce_after_checkout_billing_form', 'misha_file_upload_field' );

function misha_file_upload_field() {

	?>
		<div class="form-row form-row-wide">
			<input type="file" id="misha_file" name="misha_file" />
			<input type="hidden" name="misha_file_field" />
			<label for="misha_file"><a>Select a cool image</a></label>
			<div id="misha_filelist"></div>
		</div>
	<?php

}

Also a small bonus – let’s hide this field and display just a link instead.

#misha_file{
	position: absolute;
	height: 1px;
	width: 1px;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
}

There we go.

Now we have a link “Select cool image” that is connected to <input type="file"> HTML field.

Oh wait, maybe you don’t know where to insert the code. You can use functions.php file of your current theme, but if your theme gets updates, then I recommend you to create a child theme or add the code to a custom plugin. CSS code you can add either to .css file or to wp_head action hook.

Second, Process the File Upload via AJAX

Now let’s display the image once it is selected and process its upload via AJAX. We are going to use jQuery for that. Why? Because it is used by WooCommerce anyway!

You can create any empty JavaScript file and add the code you can see below into it. The only thing to keep in mind is the file dependency while enqueueing it, I made it dependent on wc-checkout.

jQuery( function( $ ) {

	$( '#misha_file' ).change( function() {

		if ( ! this.files.length ) {
			$( '#misha_filelist' ).empty();
		} else {

			// we need only the only one for now, right?
			const file = this.files[0];

			$( '#misha_filelist' ).html( '<img src="' + URL.createObjectURL( file ) + '"><span>' + file.name + '</span>' );

			const formData = new FormData();
			formData.append( 'misha_file', file );

			$.ajax({
				url: wc_checkout_params.ajax_url + '?action=mishaupload',
				type: 'POST',
				data: formData,
				contentType: false,
				enctype: 'multipart/form-data',
				processData: false,
				success: function ( response ) {
					$( 'input[name="misha_file_field"]' ).val( response );
				}
			});

		}

	} );

} );

Once you select the image it will be displayed in your checkout page as well.

Let’s process the upload on the server side.

add_action( 'wp_ajax_mishaupload', 'misha_file_upload' );
add_action( 'wp_ajax_nopriv_mishaupload', 'misha_file_upload' );

function misha_file_upload(){

	$upload_dir = wp_upload_dir();

	if ( isset( $_FILES[ 'misha_file' ] ) ) {
		$path = $upload_dir[ 'path' ] . '/' . basename( $_FILES[ 'misha_file' ][ 'name' ] );

		if( move_uploaded_file( $_FILES[ 'misha_file' ][ 'tmp_name' ], $path ) ) {
			echo $upload_dir[ 'url' ] . '/' . basename( $_FILES[ 'misha_file' ][ 'name' ] );
		}
	}
	die;
}

I tried to make this code as simple as possible, so I do not check the file extension, size or if it already exists in uploads folder. But I highly encourage you to do all of that and you can even display your file in WordPress media library.

Third, Save the File URL in Order Meta

Our files can be uploaded now but how do we suppose to connect them to orders? For example we can store file URLs in order meta using woocommerce_checkout_update_order_meta action hook and update_post_meta() WordPress function.

add_action( 'woocommerce_checkout_update_order_meta', 'misha_save_what_we_added' );

function misha_save_what_we_added( $order_id ){

	if( ! empty( $_POST[ 'misha_file_field' ] ) ) {
		update_post_meta( $order_id, 'misha_file_field', sanitize_text_field( $_POST[ 'misha_file_field' ] ) );
	}

}

And let’s display the uploaded images on edit order pages. More about it here.

add_action( 'woocommerce_admin_order_data_after_order_details', 'misha_order_meta_general' );

function misha_order_meta_general( $order ){

	$file = get_post_meta( $order->get_id(), 'misha_file_field', true );
	if( $file ) {
		echo '<img src="' . esc_url( $file ) . '" />';
	}

}

Done:

Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.

Need some developer help? Contact me

Follow me on Twitter