How to Prevent Duplicate Image Upload in WordPress

If you have uploaded images to WordPress using the inbuilt media uploader. then you must have noticed that duplicate images can be uploaded without any issue.

By duplicate I mean the names are same.

WordPress just renames the duplicate file, typically by introducing numeric value at the end of the file name.

But you can make sure that no two image files with the same name are uploaded. This can be done using the filter wp_handle_upload_prefilter.

This filter hook fires before the file is uploaded to the media library. So, this is where you can check for the duplicity in name and prevent the upload.

Paste the following code into your functions.php file.

add_filter( 'wp_handle_upload_prefilter', 'wp_handle_upload_prefilter_callback' );

function wp_handle_upload_prefilter_callback($file) {
    $query_images_arr = array(
        'post_type'      => 'attachment',
        'post_mime_type' => 'image',
        'post_status'    => 'inherit',
        'posts_per_page' => - 1,
    );
    
    $query_images = new WP_Query( $query_images_arr );
    
    foreach ( $query_images->posts as $image ) {
        $duplicate = false;
        $image_url = wp_get_attachment_url( $image->ID );    
        $path = parse_url($image_url, PHP_URL_PATH);    
        $name =  basename($path);
        if ( $name == $file['name'] ) {
            $file['error'] = 'Duplicate File';           
        } 
    }

    return $file;

}

The callback function wp_handle_upload_prefilter_callback is passed an instance of the $file data uploaded.

Inside the callback function we have a WordPress query to retrieve all images in media library.

$query_images_arr = array(
        'post_type'      => 'attachment',
        'post_mime_type' => 'image',
        'post_status'    => 'inherit',
        'posts_per_page' => - 1,
    );
    
    $query_images = new WP_Query( $query_images_arr );

Then we are looping through the results of this query and finding the filenames with extensions for all images. The two functions parse_url and basename are native PHP functions.

foreach ( $query_images->posts as $image ) {
        $duplicate = false;
        $image_url = wp_get_attachment_url( $image->ID );    
        $path = parse_url($image_url, PHP_URL_PATH);    
        $name =  basename($path);
        if ( $name == $file['name'] ) {
            $file['error'] = 'Duplicate File';           
        } 
    }

While inside the loop, we are also checking if the uploaded filename matches with any of the existing filesnames.

if ( $name == $file['name'] ) {
    $file['error'] = 'Duplicate File';           
} 

If the name exists then the $file array index error will have a message Duplicate File. Doing so will generate an error and the file upload will stop.

The error message shows up in the front or backend, depending on the location of upload, when we return the $file from the function.