[Bug]: Image editor silently writes PNG data into .JPG files (uppercase extension breaks canvas.toBlob MIME)
I maintainer di solito rispondono entro 2 giorni
@aniruddh18122006-cyber ci sta già lavorando.
Dal 9/10/2026.
- #3429 di @aniruddh18122006-cyber — chiusa senza merge
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 78/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- javascript
Direzione di ricerca
Inizia da src/components/ImageEditor.vue, in particolare da defaultSavedImageType() e onSave(), poi segui come la finestra di dialogo «Save image as» gestisce il campo del formato. Riproduci il problema con un’immagine con estensione .JPG maiuscola e controlla il tipo del blob codificato prima del caricamento. Il lavoro è completato quando il salvataggio preserva i byte JPEG per le estensioni maiuscole e i dati codificati non corrispondenti non vengono caricati silenziosamente.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Bug description
Editing a photo whose extension is uppercase .JPG in the built-in viewer image
editor corrupts the file: the stored bytes become PNG while the filename keeps its
.JPG extension.
Observed on Nextcloud 32.0.14.1, viewer 5.0.0, Chrome 155:
| before | after "Speichern" (save) | |
|---|---|---|
| content type | image/jpeg |
image/png |
| size | 2 865 024 B | 504 955 B |
| magic bytes | FF D8 FF |
89 50 4E 47 |
file on the server: PNG image data, 4320 x 3240, 8-bit/color RGBA.
The upload itself succeeds (PUT /remote.php/dav/files/<user>/<path>.JPG → 204),
so there is no indication anything went wrong.
Steps to reproduce
- Upload a JPEG with an uppercase extension (e.g.
ABC1234.JPG— the default
export of many cameras). - Open it in the viewer (
/apps/files/...→ click the file), pressCtrl+E
(or open with?editing=true) so the image editor opens. - Apply any change (e.g. Filters → Black & White).
- Click Save → Save image as dialog appears → Save → confirm overwrite.
- Inspect the file server-side:
file data/<user>/files/ABC1234.JPG
# PNG image data, 4320 x 3240, 8-bit/color RGBA, non-interlaced
Expected behaviour
The file must still be a JPEG (or the user must be told the format changed).
Root cause
In src/components/ImageEditor.vue (viewer 5.0.0):
defaultSavedImageType() {
return extname(this.decodedSourceName).slice(1) || 'jpeg' // -> "JPG"
}
The extension is not lower-cased. The Filerobot editor then builds the MIME
type from it ('image/' + (ext === 'jpg' ? 'jpeg' : ext)) → image/JPG.
onSave() only normalises case-sensitively:
mimeType = mimeType.replace('jpg', 'jpeg') // no-op for "image/JPG"
...
const blob = await new Promise(resolve => imageCanvas.toBlob(resolve, mimeType, quality))
const response = await axios.put(putUrl, new File([blob], fullName))
HTMLCanvasElement.toBlob() falls back to image/png for an unknown MIME type
(per spec: "if type is not a supported image format, use image/png"), so PNG
bytes are uploaded under the original .JPG name. The File's name is also not
checked against blob.type.
Consequences seen in the wild:
- PNG files that are 5–15× larger than the JPEG they replace (a 15 MB PNG was
written over a 1.4 MB JPEG in a user report). - Metadata/EXIF is lost, so Memories date/time editing then fails with
Could not set exif data: Error: Not a valid JPG (looks more like a PNG)(HTTP 500). - Previews, sync clients and third-party apps see a file whose extension lies
about its content.
Suggested fix
defaultSavedImageType() {
return (extname(this.decodedSourceName).slice(1) || 'jpeg').toLowerCase()
}
plus a defensive normalisation in onSave() (case-insensitive jpg → jpeg)
and, most importantly, a check after encoding:
if (blob.type !== mimeType) { showError(...); return } // never upload mismatched bytes
Also worth lower-casing/validating the extension in the "Save image as" dialog
(format field), which currently keeps JPG as well.
Environment
- Nextcloud 32.0.14.1, PHP 8.3.33,
viewer5.0.0 (default install) - Chrome 155, Linux
- Affected files: any image with an uppercase
.JPG/.JPEG/.PNG-style extension;
lowercase.jpgis unaffected (image/jpegworks).
- Lingua principale
- Nessun dato sulla lingua
- Stelle
- 122
- Fork
- 75
- Merge medio
- 4g 14h
- PR unite (30g)
- 45
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di nextcloud/viewer
-
[Bug] Closing a file preview calls a missing Files Sidebar methodForse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Aperta3. to review bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
I maintainer di solito rispondono entro 2 giorni
-
0. Needs triage bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 2 giorni
-
3. to review
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
nextcloud/viewer#3196 · 2 commenti ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 68/100
I maintainer di solito rispondono entro 2 giorni
Tutte le issue di nextcloud/viewer
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 83/100
I maintainer di solito rispondono entro 1 giorno
-
bug priority: high workstream:cache
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
rossoctl/context-guru#707 ·
I maintainer di solito rispondono entro 1 giorno
-
api bug entity mobai
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
Pumpkin-MC/Pumpkin#4312 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 64/100
backdrop-contrib/paragraphs#299 ·