CMM-2427: Keep the original file name when uploading media - #23328
Merged
adalpari merged 7 commits intoSep 17, 2026
Merged
Conversation
Image optimization and rotation write their output with File.createTempFile, which appends random digits to the name, and the uploaded media is named after the file we send to the server. Move the processed file to a directory of its own so it can keep the name of the file it was created from. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Collaborator
Generated by 🚫 Danger |
Contributor
|
|
Contributor
|
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## trunk #23328 +/- ##
==========================================
- Coverage 37.92% 37.91% -0.02%
==========================================
Files 2270 2271 +1
Lines 127515 127584 +69
Branches 17927 17950 +23
==========================================
+ Hits 48366 48376 +10
- Misses 75150 75209 +59
Partials 3999 3999 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Reusing the original extension when the processing step produced none would label JPEG bytes as a PNG, since those steps only write PNG when they managed to detect that format. Keep the extension they produced so the mime based repair in FluxCUtils runs as before, and delete the processed media left behind by previous sessions, which nothing else cleans up. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ShareIntentReceiverActivity already copies the shared media to the cache, naming it after the provider's display name, and forwards a file:// URI. MediaBrowserActivity.uploadList then passes that URI to fetchMedia(), whose isInMediaStore() guard only matches content://media/, so the file:// URI falls through and is copied a second time. That copy reads its name from OpenableColumns.DISPLAY_NAME, and querying the content resolver for a file:// URI resolves no provider and returns null, so the name drops to the wp-<timestamp> fallback. It is the app, not an exotic content provider, that renames media shared into it. Return a file:// URI as it is instead, so the name the share activity resolved is the one that gets uploaded. A URI whose file is missing still takes the download path, so its failure is reported the way it is today. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
adalpari
marked this pull request as ready for review
September 16, 2026 09:45
The cropped image is now uploaded straight from disk, so the fixed cacheDir path meant a second icon change overwrote the bytes the previous upload was still streaming. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The purge only knew about the file age, so it dropped the only local copy of media queued offline or failing to upload, leaving it with nothing left to send. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
adalpari
enabled auto-merge (squash)
September 17, 2026 12:35
adalpari
deleted the
cmm-2427-file-names-are-not-retained-when-uploading-images
branch
September 17, 2026 12:48
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


TL;DR
There was a reported bug about the app adding a prefix or suffix when uploading images and videos. The name the media gets on the site comes from the file we upload, not from the title we set on it. The image optimizer and the rotation were writing their result to a new file with random digits added, and the video optimizer was naming its output after a timestamp. We were also copying shared media to the cache twice, and the second copy lost the original name and got a wp- prefix instead.
Description
Fixes CMM-2427 / #20468: media uploaded from the app arrives on the site renamed to something like
wp-1710415123456938475.The name a media item gets on the site is decided by the on-disk file name, not by
MediaModel.fileName:MediaRSApiRestClient.uploadMediabuildsMediaCreateParams(title, filePath)and the wordpress-rs binding has no filename parameter, so for application-password and self-hosted sites the basename offilePathis what the server sees. Any fix therefore has to rename the file itself.Two separate things mangle that name, both in the external
org.wordpress:utilslibrary:MediaUtils.downloadExternalMedianames the cache copy afterOpenableColumns.DISPLAY_NAME, falling back togenerateTimeStampedFileName()→wp-<currentTimeMillis>.<ext>when that lookup comes back empty — which it always does for afile://URI, since the content resolver resolves no provider for thefilescheme and returns null.ImageUtils.optimizeImage/rotateImageIfNecessarywrite their result withFile.createTempFile(prefix, ext), which appends 10–19 random digits. Image optimization is on by default, so this hit every image upload, even when the name survived step 1.VideoOptimizerdid the same thing deliberately, generating awp-<timestamp>.mp4name.wp-+ 13 digits + ~10 random digits is exactly the reported string.The app walks into cause 1 by itself, by copying shared media to the cache twice.
ShareIntentReceiverActivity.addLocalMediaUricopies it once and gets the name right, then forwards afile://URI.MediaBrowserActivity.uploadListpasses that toWPMediaUtils.fetchMedia, whoseMediaUtils.isInMediaStore()guard only matchescontent://media/— so thefile://URI falls through and is copied again, and that second copy is where the name is lost. No exotic content provider is needed: sharing a perfectly named local photo into the app reproduced it.This PR fixes both causes (and the video equivalent):
WPMediaUtils.fetchMedia(): returns afile://URI as it is instead of downloading it again, since it already points at a local copy. That removes the second copy, so the name the share activity resolved is the one that gets uploaded — and saves a redundant copy of every shared file. Afile://URI whose file is missing still takes the download path, so its failure is still reported the way it is today.MediaFileNameUtils(new, Kotlin): combines the original base name with the extension of the processed file, taken verbatim.ImageUtilsonly writes PNG when it managed to detect that format and writes JPEG otherwise, leaving a bare trailing dot when detection fails — which it does for names containing spaces, the case the existingFluxCUtils.mediaModelFromLocalUriworkaround comments on. Reusing the original extension there would label JPEG bytes as a PNG, so the missing extension is left missing and repaired from the mime type byFluxCUtils, exactly as it already is today. Covered by unit tests.WPMediaUtils:getOptimizedMedia()andfixOrientationIssue()now move their result intocacheDir/processed-media/<counter>/, one directory per file, so the original name can be restored verbatim without a collision-dodging suffix. No-op when the util returned the input path unchanged (gif, unreadable dimensions, optimization disabled); falls back to the temp path if the rename fails.VideoOptimizer: names the optimized video after the source media (clip.mov→clip.mp4) instead ofwp-<timestamp>.mp4, writing it through the same helper. Keeps the timestamped name as a fallback when the media has no file name.WPMediaUtils.deleteOldProcessedMedia(), called fromAppInitializer: nothing else prunes that new directory —ImageEditorInitializeronly handlescache/media-editingandWordPressDB.clearEmptyCacheFilesonly removes zero-length files from the cache root, non-recursively — and a failed video optimization leaves its output behind. Entries older than a week are now deleted at app init, matching the image editor's retention. A week is deliberately generous so it can't race an upload being retried across restarts.Not covered
Cause 1 is only fixed where the app caused it. A content provider that genuinely reports no
DISPLAY_NAMEstill leaves no name to keep, so media coming from one is still calledwp-1710415123456.jpg. Removing that last fallback needs a change in WordPress-Utils-Android.downloadExternalMediaalso dodges collisions in the cache root by appending-1,-2, ... to the name. Now that the share activity's copy is the one being uploaded, re-sharing a file whose name is still in the cache uploads it asphoto-1.jpg. That is pre-existing behaviour and matches what the server does with duplicate names, so it is left alone.VideoOptimizerBasehas the identical defect but has no subclasses (onlyVideoOptimizeris instantiated, fromMediaUploadHandler), so it was left alone as dead code.Testing instructions
Image optimization is on by default; leave it enabled (Me → App Settings → Optimize images).
Upload from the Media library:
PXL_20240314_120000.jpg.wp-prefix.Share into the app (the
wp-prefix):wp-followed by digits.Upload from the post editor:
File names with spaces (the case where format detection fails):
my holiday photo.jpg..jpg(this used to be dropped by path resolution).my holiday photo.png..png.Video optimization:
.mp4extension.