-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Client-side media processing creates duplicate sub-size files for same-dimension image sizes #77035
Description
Description
When themes register image sizes with the same dimensions as WordPress built-in sizes, client-side media processing creates duplicate physical files on disk. For example, with Twenty Eleven active:
medium_large(768x1024) andlarge(768x1024) → two separate files:IMG-768x1024.jpegandIMG-768x1024-1.jpegmedium(225x300) andsmall-feature(225x300) →IMG-225x300.jpegandIMG-225x300-1.jpegpost-thumbnail(1000x288) andlarge-feature(1000x288) →IMG-1000x288.jpegandIMG-1000x288-1.jpeg
Server-side uploads via the media library does not create duplicates.
Steps to reproduce
- Activate a theme that registers image sizes matching built-in dimensions (e.g., Twenty Eleven)
- Enable client-side media processing (requires compatible browser with SharedArrayBuffer)
- Upload a large image (above big image threshold)
- Check the uploads directory — duplicate files exist with
-1suffixes
Expected behavior
When multiple registered image sizes have the same effective dimensions (width, height, crop), only one physical file should be created and shared across size names in the metadata.
Root cause
In generateThumbnails (packages/upload-media/src/store/private-actions.ts), the code iterates every entry in missing_image_sizes and creates a separate sideload item for each without checking if multiple size names map to the same dimensions. Each sideload generates a separate physical file (VIPS resize + upload), and the server appends -1 via wp_unique_filename() to avoid filename collisions.
Proposed fix
Deduplicate sizesToGenerate by dimensions before the sideload loop. Group size names by their effective dimensions (width, height, crop) and only generate/sideload one physical file per unique dimension set. The remaining size names in each group should reference the same file in metadata.
const generatedDimensions = new Set<string>();
for ( const name of sizesToGenerate ) {
const imageSize = allImageSizes[ name ];
const key = `${imageSize.width}x${imageSize.height}x${imageSize.crop}`;
if ( generatedDimensions.has( key ) ) {
continue; // Skip — another size with same dimensions already queued
}
generatedDimensions.add( key );
// ... create sideload item ...
}Note: This simple approach skips duplicate dimension sizes entirely, which means those size names won't appear in metadata.
Testing
An E2E test should be added that:
- Registers custom image sizes with dimensions matching built-in sizes
- Uploads an image with client-side processing enabled
- Verifies no duplicate physical files are created (no
-1suffix files) - Verifies all registered size names appear in attachment metadata with correct file references
Screenshots
Client-side upload
note duplicate sizes with -1
Server-side upload
No duplicates
