Skip to content

Instantly share code, notes, and snippets.

@espenmn
Last active November 22, 2025 20:54
Show Gist options
  • Select an option

  • Save espenmn/e4ca0b1eb11b303850ddbaaa0e3ae2d3 to your computer and use it in GitHub Desktop.

Select an option

Save espenmn/e4ca0b1eb11b303850ddbaaa0e3ae2d3 to your computer and use it in GitHub Desktop.
Alternative 1
----------------
/**
* Prevent duplicate image uploads based on file name.
*/
function prevent_duplicate_image_upload( $file ) {
// Only act on image uploads
if ( strpos( $file['type'], 'image/' ) !== 0 ) {
return $file;
}
$filename = basename( $file['name'] );
// Strip the extension — this is what WordPress uses as post_title
$title = pathinfo( $filename, PATHINFO_FILENAME );
// Look for existing attachment with the same title
$existing = get_page_by_title( $title, OBJECT, 'attachment' );
if ( $existing ) {
// Stop upload — show error message in the uploader
$file['error'] = sprintf(
'Upload blocked: The file "%s" already exists in the media library (Attachment ID: %d).',
esc_html( $filename ),
$existing->ID
);
}
return $file;
}
add_filter( 'wp_handle_upload_prefilter', 'prevent_duplicate_image_upload' );
Alternative 2 by hsash
--------------------------
function prevent_duplicate_image_upload_by_hash( $file ) {
if ( strpos( $file['type'], 'image/' ) !== 0 ) {
return $file;
}
$new_file_hash = md5_file( $file['tmp_name'] );
// Query attachments and compare hashes
$attachments = get_posts( array(
'post_type' => 'attachment',
'posts_per_page' => -1,
'post_mime_type' => 'image',
'fields' => 'ids'
) );
foreach ( $attachments as $attach_id ) {
$existing_path = get_attached_file( $attach_id );
if ( $existing_path && file_exists( $existing_path ) ) {
if ( md5_file( $existing_path ) === $new_file_hash ) {
$file['error'] = sprintf(
'Upload blocked: An identical image already exists (Attachment ID: %d).',
$attach_id
);
break;
}
}
}
return $file;
}
add_filter( 'wp_handle_upload_prefilter', 'prevent_duplicate_image_upload_by_hash' );
Alternative 3, probably not a good idea, by custom upload page
-------------------------
// Upload page for multiple image upload form
// Skipping images that exists already
// not sure what to restrict on, maybe:
// To restrict access (e.g., only logged-in users):
//if (!is_user_logged_in()) {
// wp_die('You must be logged in to upload images.');
//}
// 1. Register a custom rewrite endpoint for the upload page
function custom_upload_page_rewrite() {
add_rewrite_rule('^upload-images/?$', 'index.php?custom_upload_page=1', 'top');
}
add_action('init', 'custom_upload_page_rewrite');
// 2. Add query var for our endpoint
function custom_upload_page_query_vars($vars) {
$vars[] = 'custom_upload_page';
return $vars;
}
add_filter('query_vars', 'custom_upload_page_query_vars');
// 3. Display the upload form when visiting /upload-images/
function custom_upload_page_template() {
if (intval(get_query_var('custom_upload_page')) === 1) {
// Handle upload submission
if (isset($_POST['custom_image_upload_nonce']) && wp_verify_nonce($_POST['custom_image_upload_nonce'], 'custom_image_upload')) {
if (!function_exists('wp_handle_upload')) {
require_once(ABSPATH . 'wp-admin/includes/file.php');
}
$upload_overrides = array('test_form' => false);
$files = $_FILES['custom_images'];
echo '<div style="padding:20px;font-family:sans-serif;">';
foreach ($files['name'] as $key => $value) {
if ($files['name'][$key]) {
$file = array(
'name' => $files['name'][$key],
'type' => $files['type'][$key],
'tmp_name' => $files['tmp_name'][$key],
'error' => $files['error'][$key],
'size' => $files['size'][$key]
);
$file_name = basename($file['name']);
$existing = get_page_by_title($file_name, OBJECT, 'attachment');
if ($existing) {
echo '<p style="color:red;">Skipped: <strong>' . esc_html($file_name) . '</strong> already exists (ID: ' . $existing->ID . ')</p>';
continue;
}
$movefile = wp_handle_upload($file, $upload_overrides);
if ($movefile && !isset($movefile['error'])) {
// Insert attachment
$attachment = array(
'guid' => $movefile['url'],
'post_mime_type' => $movefile['type'],
'post_title' => $file_name,
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment($attachment, $movefile['file']);
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attach_data = wp_generate_attachment_metadata($attach_id, $movefile['file']);
wp_update_attachment_metadata($attach_id, $attach_data);
echo '<p style="color:green;">Uploaded: <strong>' . esc_html($file_name) . '</strong> (ID: ' . $attach_id . ')</p>';
} else {
echo '<p style="color:red;">Error uploading <strong>' . esc_html($file_name) . '</strong>: ' . esc_html($movefile['error']) . '</p>';
}
}
}
echo '</div>';
}
// Output the HTML form.
?>
<div style="max-width:600px;margin:50px auto;padding:20px;border:1px solid #ccc;border-radius:10px;font-family:sans-serif;">
<h2>Upload Images</h2>
<p>Avoid duplicate files upload</p>
<form method="post" enctype="multipart/form-data">
<?php wp_nonce_field('custom_image_upload', 'custom_image_upload_nonce'); ?>
<p><label>Select Images:</label><br>
<input type="file" name="custom_images[]" accept="image/*" multiple required></p>
<input type="submit" value="Upload Images">
</form>
</div>
<?php
exit; // Stop WordPress from loading a normal page template
}
}
add_action('template_redirect', 'custom_upload_page_template');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment