skip to Main Content

i have created a custom plugin which dynamically displays custom fields in woocommerce single product page.
Fields are displayed, added to cart and added to order data and emails.
However i’m trying for days to add a file upload field with no luck.
The field is displayed in the frontend like:

add_action( 'woocommerce_before_add_to_cart_button', 'display_custom_fields' );
function display_custom_fields() {
?>
    <p class="form-row validate-required" id="image" >
        <span class="woocommerce-input-wrapper">
        <label for="image" class=""><?php echo $stamp_welcome_text; ?> </label> 
        
        <input type="file" name="image" accept="image/*" >
        </span>
    </p>
<?php
}

and then added to cart like:

add_filter( 'woocommerce_add_cart_item_data', 'add_cart_item_data', 10,3 );
function add_cart_item_data( $cart_item_data, $product_id ) {
    if ($_FILES['image'] ) {
        require_once( ABSPATH . 'wp-admin/includes/image.php' );
        require_once( ABSPATH . 'wp-admin/includes/file.php' );
        require_once( ABSPATH . 'wp-admin/includes/media.php' );
        $attachment_id = media_handle_upload( 'image', 0 );
        if ( is_wp_error( $attachment_id ) AND $_FILES['image']['size'] > 0) {
            die($attachment_id->get_error_message().'. Παρακαλώ επικοινωνήστε μαζί μας.');
        } else $cart_item_data['image'] = $attachment_id;
    }
    return $item_cart_data;
}

Of course this is only part of the code.The rest of the fields are working perfect. Yes, i have tried the code only by itself if anyone wonders.

I have been "playing" around with it for days and i can’t figure out what’s wrong.
Any help is highly appreciated 🙂

4

Answers


  1. Chosen as BEST ANSWER

    I managed to find a conflict with my template(woodmart) the code works perfectly on twentytwenty and storefront

    i should have thought of this earlier and not bang my head in the wall for a week.


  2. You can do this using a plugin such as Product Addons

    https://woocommerce.com/products/product-add-ons/

    Here’s a link to the documentation that explains specifically about allowing file uploads (they can be free or charge per upload)

    https://docs.woocommerce.com/document/product-add-ons/#section-9

    Hope this helps!

    Login or Signup to reply.
  3. You could try the following, that will store uploaded image data as custom cart item data and save it as custom order item meta data:

    // Display additional product fields (+ jQuery code)
    add_action( 'woocommerce_before_add_to_cart_button', 'display_additional_product_fields', 9 );
    function display_additional_product_fields(){
        ?>
        <p class="form-row validate-required" id="image" >
            <label for="file_field"><?php echo __("Upload Image") . ': '; ?>
                <input type='file' name='image' accept='image/*'>
            </label>
        </p>
        <?php
    }
    
    
    // Add custom fields data as the cart item custom data
    add_filter( 'woocommerce_add_cart_item_data', 'add_custom_fields_data_as_custom_cart_item_data', 10, 2 );
    function add_custom_fields_data_as_custom_cart_item_data( $cart_item, $product_id ){
        if( isset($_FILES['image']) && ! empty($_FILES['image']) ) {
            $upload       = wp_upload_bits( $_FILES['image']['name'], null, file_get_contents( $_FILES['image']['tmp_name'] ) );
            $filetype     = wp_check_filetype( basename( $upload['file'] ), null );
            $upload_dir   = wp_upload_dir();
            $upl_base_url = is_ssl() ? str_replace('http://', 'https://', $upload_dir['baseurl']) : $upload_dir['baseurl'];
            $base_name    = basename( $upload['file'] );
    
            $cart_item['file_upload'] = array(
                'guid'      => $upl_base_url .'/'. _wp_relative_upload_path( $upload['file'] ), // Url
                'file_type' => $filetype['type'], // File type
                'file_name' => $base_name, // File name
                'title'     => ucfirst( preg_replace('/.[^.]+$/', '', $base_name ) ), // Title
            );
            $cart_item['unique_key'] = md5( microtime().rand() ); // Avoid merging items
        }
        return $cart_item;
    }
    
    // Display custom cart item data in cart (optional)
    add_filter( 'woocommerce_get_item_data', 'display_custom_item_data', 10, 2 );
    function display_custom_item_data( $cart_item_data, $cart_item ) {
        if ( isset( $cart_item['file_upload']['title'] ) ){
            $cart_item_data[] = array(
                'name' => __( 'Image uploaded', 'woocommerce' ),
                'value' =>  str_pad($cart_item['file_upload']['title'], 16, 'X', STR_PAD_LEFT) . '…',
            );
        }
        return $cart_item_data;
    }
    
    // Save Image data as order item meta data
    add_action( 'woocommerce_checkout_create_order_line_item', 'custom_field_update_order_item_meta', 20, 4 );
    function custom_field_update_order_item_meta( $item, $cart_item_key, $values, $order ) {
        if ( isset( $values['file_upload'] ) ){
            $item->update_meta_data( '_img_file',  $values['file_upload'] );
        }
    }
    
    // Admin orders: Display a linked button + the link of the image file
    add_action( 'woocommerce_after_order_itemmeta', 'backend_image_link_after_order_itemmeta', 10, 3 );
    function backend_image_link_after_order_itemmeta( $item_id, $item, $product ) {
        // Only in backend for order line items (avoiding errors)
        if( is_admin() && $item->is_type('line_item') && $file_data = $item->get_meta( '_img_file' ) ){
            echo '<p><a href="'.$file_data['guid'].'" target="_blank" class="button">'.__("Open Image") . '</a></p>'; // Optional
            echo '<p><code>'.$file_data['guid'].'</code></p>'; // Optional
        }
    }
    
    // Admin new order email: Display a linked button + the link of the image file
    add_action( 'woocommerce_email_after_order_table', 'wc_email_new_order_custom_meta_data', 10, 4);
    function wc_email_new_order_custom_meta_data( $order, $sent_to_admin, $plain_text, $email ){
        // On "new order" email notifications
        if ( 'new_order' === $email->id ) {
            foreach ($order->get_items() as $item ) {
                if ( $file_data = $item->get_meta( '_img_file' ) ) {
                    echo '<p>
                        <a href="'.$file_data['guid'].'" target="_blank" class="button">'.__("Download Image") . '</a><br>
                        <pre><code style="font-size:12px; background-color:#eee; padding:5px;">'.$file_data['guid'].'</code></pre>
                    </p><br>';
                }
            }
        }
    }
    

    This code goes in functions.php file of your active child theme (or active theme).

    Tested in Woocommerce version 4.3.x and working with default WooCommerce products from all types.

    Login or Signup to reply.
  4. For multiple images if someone needs it.

    function add_custom_fields_data_as_custom_cart_item_data($cart_item)
    {
        $images = ['front-image', 'back-image', 'sleeve-image'];
    
        foreach ($images as $image) {
            if (isset($_FILES[$image]) && $_FILES[$image]['error'] === 0) {
    
                $upload       = wp_upload_bits($_FILES[$image]['name'], null, file_get_contents($_FILES[$image]['tmp_name']));
                $filetype     = wp_check_filetype(basename($upload['file']), null);
                $upload_dir   = wp_upload_dir();
                $upl_base_url = is_ssl() ? str_replace('http://', 'https://', $upload_dir['baseurl']) : $upload_dir['baseurl'];
                $base_name    = basename($upload['file']);
    
                $cart_item['file_upload'][] = array(
                    'guid'      => $upl_base_url . '/' . _wp_relative_upload_path($upload['file']), // Url
                    'file_type' => $filetype['type'], // File type
                    'file_name' => uniqid('logo_upload') . $base_name, // File name
                    'title'     => ucfirst(preg_replace('/.[^.]+$/', '', $base_name)), // Title
                    'position' => $image
                );
                $cart_item['unique_key'] = md5(microtime() . rand()); // Avoid merging items
            }
        }
        return $cart_item;
    }
    add_filter('woocommerce_add_cart_item_data', 'add_custom_fields_data_as_custom_cart_item_data', 10, 3);
    
    
    // Display custom cart item data in cart 
    add_filter('woocommerce_get_item_data', 'display_custom_item_data', 10, 2);
    function display_custom_item_data($cart_item_data, $cart_item)
    {
    
        foreach ($cart_item['file_upload'] as $image) {
            if (isset($image['title'])) {
                $cart_item_data[] = array(
                    'name' => __('Image uploaded', 'woocommerce'),
                    'value' =>  $image['title']
                );
            }
        }
        return $cart_item_data;
    }
    
    // Save Image data as order item meta data
    add_action('woocommerce_checkout_create_order_line_item', 'custom_field_update_order_item_meta', 20, 4);
    function custom_field_update_order_item_meta($item, $cart_item_key, $values, $order)
    {
        if (isset($values['file_upload'])) {
            $item->update_meta_data('_img_files',  $values['file_upload']);
        }
    }
    
    // Admin orders: Display a linked button + the link of the image file
    add_action('woocommerce_after_order_itemmeta', 'backend_image_link_after_order_itemmeta', 10, 3);
    function backend_image_link_after_order_itemmeta($item_id, $item, $product)
    {
        // Only in backend for order line items (avoiding errors)
        if (is_admin() && $item->is_type('line_item') && $files_data = $item->get_meta('_img_files')) {
    
            $imagesHtml = '';
    
            foreach ($files_data as $key => $image) {
                $imagesHtml .= '<p><a href="' . $image['guid'] . '" target="_blank" class="button">' . __($image['position']) . '</a></p>'; // Optional
            }
    
            echo $imagesHtml;
            
        }
    }
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search