fix(image): label thumbnails by their bytes, not the source's name #173

Merged
cameron merged 1 commits from fix/thumb-content-type into master 2026-10-16 19:55:23 +00:00
Owner

Legacy thumbnail and preview paths mirror the source's relative path, so
a video's JPEG thumbnail lives at …/clip.mp4 and a RAW's at
…/shot.arw. NamedFile guessed the content type from that name and
served JPEG bytes as video/mp4. Sniff JPEG/PNG magic bytes instead.

The circular-thumbnail path had the same root cause: image::open
picks the decoder from the extension, so it failed on those thumbs and
quietly fell back to the square one. Guess the format from the bytes.

Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com

Legacy thumbnail and preview paths mirror the source's relative path, so a video's JPEG thumbnail lives at `…/clip.mp4` and a RAW's at `…/shot.arw`. NamedFile guessed the content type from that name and served JPEG bytes as `video/mp4`. Sniff JPEG/PNG magic bytes instead. The circular-thumbnail path had the same root cause: `image::open` picks the decoder from the extension, so it failed on those thumbs and quietly fell back to the square one. Guess the format from the bytes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cameron added 1 commit 2026-10-16 19:52:16 +00:00
Legacy thumbnail and preview paths mirror the source's relative path, so
a video's JPEG thumbnail lives at `…/clip.mp4` and a RAW's at
`…/shot.arw`. NamedFile guessed the content type from that name and
served JPEG bytes as `video/mp4`. Sniff JPEG/PNG magic bytes instead.

The circular-thumbnail path had the same root cause: `image::open`
picks the decoder from the extension, so it failed on those thumbs and
quietly fell back to the square one. Guess the format from the bytes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cameron merged commit fca9a28cee into master 2026-10-16 19:55:23 +00:00
cameron deleted branch fix/thumb-content-type 2026-10-16 19:55:23 +00:00
Sign in to join this conversation.