Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/gunjanjaswal/wordpress-unique-upload/archive/refs/heads/main.zipUnique Upload Filenames
A tiny companion plugin for OffloadForge - Cloud Media Offload
Stops same-named uploads from silently overwriting each other on your cloud bucket.
Pairs with OffloadForge - Cloud Media Offload. Get it on WordPress.org or GitHub. This add-on protects OffloadForge's remove local files option from the filename clash described below.
Why this exists
If you offload your media to the cloud with OffloadForge and you have the remove local files option switched on, WordPress loses the one thing it relies on to keep filenames unique.
Here is the chain of events, step by step:
- You upload
photo.jpg. OffloadForge pushes it to your bucket and then deletes the local copy to save disk space. - A week later, a different
photo.jpgis uploaded (and yes, a lot of AI image tools happily export everything asunknown.pngorimage.png). - WordPress checks for a clash with
wp_unique_filename(), but that function only looks at the local uploads folder, which is now empty. - Seeing no clash, WordPress keeps the name
photo.jpgand the second file overwrites the first one on the bucket.
The result is quietly nasty: one post suddenly shows another post's featured image, social share previews point at the wrong picture, and nothing in the dashboard tells you what happened. The files look fine in the Media Library because the thumbnails were generated separately. Only the full-size original gets clobbered.
Unique Upload Filenames closes that gap. It gives every new upload a short unique suffix before the file is ever written, so two uploads can never land on the same path.
How it works
The plugin hooks into WordPress right when an upload arrives and rewrites the filename, adding a compact date plus random token:
unknown.png -> unknown-261019-a3f90c.png
festival-poster.png -> festival-poster-261019-7b2e14.png
IMG_4471.jpg -> IMG_4471-261019-c0d9fa.jpg
- The descriptive part of the name is kept, so your URLs stay readable.
261019is the date (YYMMDD) and the six characters after it are random hex, so even two uploads of the same file on the same day get different names.- It runs for both browser uploads (Media Library, block editor, classic editor) and programmatic imports (
wp media import,media_sideload_image). - Generated thumbnail sizes inherit the unique base, so every size is unique too.
No database tables, no admin screen, no settings to get wrong. Drop it in and forget it.
Table of contents
- Installation
- Compatibility
- Developer filters
- FAQ
- Before and after
- Changelog
- Contributing
- Support
- Author
- License
Installation
You can run this as a normal plugin or as a must-use plugin. Pick whichever fits how you manage the site.
Option A: as a regular plugin
- Download this repository as a ZIP, or clone it.
- Copy the folder into
wp-content/plugins/. - Go to Plugins in wp-admin and click Activate on Unique Upload Filenames for OffloadForge.
Option B: as a must-use plugin (always on, cannot be deactivated by accident)
- Copy
unique-upload-filenames.phpintowp-content/mu-plugins/. - Create that folder first if it does not exist.
That is the whole setup. There is nothing to configure.
Note on existing files: the plugin only renames new uploads. Files already in your Media Library are left exactly as they are.
Compatibility
| Works with | Notes |
|---|---|
| OffloadForge - Cloud Media Offload (GitHub) | This is the add-on's main target. Recommended whenever remove local files is enabled. |
| Any other offload or CDN plugin | The same overwrite problem exists with any plugin that removes local copies. This fixes all of them. |
| Vanilla WordPress with no offload | Harmless. You get guaranteed-unique names and never see WordPress's -1, -2, -3 suffixes again. |
| Multisite | Works per site. Each upload gets its own unique name. |
Requirements: WordPress 5.0 or newer, PHP 7.0 or newer.
Developer filters
Everything is optional. The defaults are sensible, but if you want to shape the behaviour, three filters are available.
| Filter | What it does | Default |
|---|---|---|
wuuf_enabled |
Return false to skip renaming for a given upload. |
true |
wuuf_token |
Change the token that gets appended to the base name. | YYMMDD-xxxxxx |
wuuf_filename |
Override the final filename after it has been built. | the rewritten name |
Examples
Turn the renaming off for a specific file type:
add_filter( 'wuuf_enabled', function ( $enabled, $file ) {
if ( isset( $file['name'] ) && str_ends_with( $file['name'], '.svg' ) ) {
return false; // leave SVG icons with their original names
}
return $enabled;
}, 10, 2 );
Use a plain timestamp instead of the date-plus-random token:
add_filter( 'wuuf_token', function () {
return (string) time();
} );
Lowercase every uploaded filename while you are at it:
add_filter( 'wuuf_filename', function ( $new_name ) {
return strtolower( $new_name );
} );
FAQ
Will this rename the files I already uploaded? No. It only touches new uploads. Your existing library is untouched.
Do my URLs become ugly random strings?
Not really. The original name stays in front, so holiday-banner.png becomes holiday-banner-261019-a3f90c.png. Still readable, still searchable, just safe.
I do not use OffloadForge. Is this still useful?
Yes. Any time local files are removed after an offload, the same overwrite risk exists. Even without any offload plugin, you simply stop seeing WordPress's automatic -1, -2 renames because every name is unique from the start.
Does it slow uploads down? No. It generates a few random bytes and rewrites a string. There are no network calls and no database lookups.
Can I use it as a must-use plugin?
Yes, and that is often the better choice on a production site because it cannot be switched off from the dashboard by mistake. Just drop the PHP file into wp-content/mu-plugins/.
What about thumbnail sizes? They inherit the unique base name, so every generated size is unique too.
Before and after
Without the plugin, with local files removed after offload:
Upload 1: photo.jpg -> bucket: /uploads/2026/10/photo.jpg
Upload 2: photo.jpg -> bucket: /uploads/2026/10/photo.jpg (overwrites upload 1)
With the plugin:
Upload 1: photo.jpg -> bucket: /uploads/2026/10/photo-261019-a3f90c.jpg
Upload 2: photo.jpg -> bucket: /uploads/2026/10/photo-261019-7b2e14.jpg (safe, separate file)
Changelog
1.0.0
- First release.
- Appends a unique
YYMMDD-xxxxxxtoken to every upload, so same-name files cannot overwrite each other on the bucket. - Built as a companion for OffloadForge - Cloud Media Offload, while working with any offload or CDN plugin.
- Covers browser uploads and programmatic sideloads (
wp media import,media_sideload_image). - Adds the
wuuf_enabled,wuuf_token, andwuuf_filenamefilters.
Contributing
Issues and pull requests are welcome. If you hit an edge case with a particular offload setup, open an issue with the steps to reproduce and I will take a look.
Support
If this saved you from a confusing afternoon of swapped images, you can say thanks here:
Questions or ideas: hello@gunjanjaswal.me
Author
Gunjan Jaswal
- Website: www.gunjanjaswal.me
- GitHub: @gunjanjaswal
- Email: hello@gunjanjaswal.me
License
Released under the GPL-2.0-or-later license, the same license WordPress itself uses. You are free to use, change, and share it.