mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-22 23:01:48 +00:00
fix: serve real thumbnails for local photos instead of full-resolution originals (#822)
Add thumbnailService that lazy-generates a WebP thumbnail (800px max, q80) on first GET /api/photos/:id/thumbnail request using sharp. The generated file is stored at uploads/journey/thumbs/<sha1>.webp and the path is persisted to trek_photos.thumbnail_path so subsequent requests are served directly from disk. Also populates width/height as a side-effect. streamPhoto now branches on kind for local file_path rows — thumbnail requests use the stored/generated thumb path; original requests (and fallback when thumb generation fails) continue to serve the full file. Remote providers (Immich, Synology) are unaffected.
This commit is contained in:
@@ -9,6 +9,7 @@ import type { ServiceResult, AssetInfo } from './helpersService';
|
||||
import { fail, success } from './helpersService';
|
||||
import { encrypt_api_key, decrypt_api_key } from '../apiKeyCrypto';
|
||||
import * as photoCache from './trekPhotoCache';
|
||||
import { ensureLocalThumbnail } from './thumbnailService';
|
||||
|
||||
// ── Lookup / Register ────────────────────────────────────────────────────
|
||||
|
||||
@@ -101,7 +102,31 @@ export async function streamPhoto(
|
||||
}
|
||||
|
||||
if (photo.file_path) {
|
||||
const localPath = path.join(__dirname, '../../../uploads', photo.file_path);
|
||||
const uploadsRoot = path.join(__dirname, '../../../uploads');
|
||||
|
||||
if (kind === 'thumbnail') {
|
||||
let thumbRel = photo.thumbnail_path ?? null;
|
||||
if (!thumbRel) {
|
||||
const result = await ensureLocalThumbnail(uploadsRoot, photo.file_path);
|
||||
if (result) {
|
||||
thumbRel = result.thumbnailRelPath;
|
||||
db.prepare(
|
||||
'UPDATE trek_photos SET thumbnail_path = ?, width = COALESCE(width, ?), height = COALESCE(height, ?) WHERE id = ?'
|
||||
).run(thumbRel, result.width, result.height, photo.id);
|
||||
}
|
||||
}
|
||||
if (thumbRel) {
|
||||
const thumbAbs = path.join(uploadsRoot, thumbRel);
|
||||
if (fs.existsSync(thumbAbs)) {
|
||||
res.set('Cache-Control', 'public, max-age=86400, immutable');
|
||||
res.sendFile(thumbAbs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Fall through to original if thumbnail unavailable.
|
||||
}
|
||||
|
||||
const localPath = path.join(uploadsRoot, photo.file_path);
|
||||
if (fs.existsSync(localPath)) {
|
||||
res.set('Cache-Control', 'public, max-age=86400');
|
||||
res.sendFile(localPath);
|
||||
|
||||
Reference in New Issue
Block a user