Upload multiple files in randomly generated folder using wp_upload_bits

The question:

Trying to upload multiple files in randomly generated folder in different path than usual uploads/year/month by using wp_upload_bits.

Here is my code:

$randomFolder = '';

function file_upload_callback() {
    global $wpdb;
    $table_name = 'wp_order_quotes_real';
    $_filter = true;
    add_filter( 'upload_dir', function( $arr ) use( &$_filter){
        if ( $_filter ) {
            if ($randomFolder == '') {
                $randomFolder = substr(str_shuffle("0123456789abcdefghijklmnopqrstvwxyz"), 0, 16);
            }
            $arr['path'] = $arr['basedir'].'/order-quotes/'.$randomFolder;
            return $arr;
        }
    });
    _filter = false;    

    for($i=0; $i < $countfiles; $i++) {
        $upload = wp_upload_bits($_FILES['file']['name'][$i], null, file_get_contents($_FILES['file']['tmp_name'][$i]));
        
    }
    $dataSubmission = $wpdb->insert( 
        $table_name, array( 
            'order_id' => $order_id,
            'user_id' =>  $user_id ?? 'NULL',
            'category' => $cart
        ),
        array(
          '%d', '%d'
        )
    );
    
    
    wp_die();
}
add_action( 'wp_ajax_file_upload', 'file_upload_callback' );

If I upload 3 files, it creates three folders with random names and upload single file in each folder. I want to upload all the files in single generated folder in /order-quotes/ folder

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

Apply the following fixes (those with the // Fix <number>: comment) and your code would work in that only one random folder that will be created for all the uploads in the current session: (Note: I presumed the $countfiles is properly defined in your actual code.)

function file_upload_callback() {
    global $wpdb;
    $table_name = 'wp_order_quotes_real';

    $_filter = true;
    $randomFolder = ''; // Fix 1: Define the variable.

    // Fix 2: Pass $randomFolder by reference to the closure below. That way, the
    // value won't be changed when the hook calls the closure the next time.
    add_filter( 'upload_dir', function( $arr ) use ( &$_filter, &$randomFolder ) {
        if ( $_filter ) {
            if ($randomFolder == '') {
                $randomFolder = ... your code;
            }
            $arr['path'] = $arr['basedir'].'/order-quotes/'.$randomFolder;
            // Note: I moved the `return` line to below.
        }
        return $arr; // Fix 3: ALWAYS return it!
    });
    //$_filter = false; // Fix 4: Don't disable it, yet.

    for($i=0; $i < $countfiles; $i++) {
        // Note: You should do this because the user may not necessariy upload the
        // files in sequence, i.e. file input two might be empty and the user only
        // selected a file for the first and third inputs..
        if ( empty( $_FILES['file']['tmp_name'][ $i ] ) ) {
            continue;
        }

        $upload = wp_upload_bits( ... your code here... );

    }
    $_filter = false; // Fix 5: Now you should disable the filter because all the
                      // uploads have completed.

    // ... the rest of your code here.
}

Additionally, instead of hardcoding the table name, you should do $table_name = $wpdb->prefix . 'order_quotes_real';. More importantly, please apply security measures like checking user capabilities and intent of the specific request.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment