EXIF round-trip: read before upload, re-embed server-side

- Client: exifr.parse() reads full EXIF before upload, sent as exif_data
- Server: piexif re-embeds EXIF into saved JPEG after upload
- Auto-extract GPS from picked gallery photos on selection
- Removed Google Photos button (needs OAuth, not feasible)
This commit is contained in:
2026-05-21 21:29:55 -04:00
parent 906b61143a
commit 78dbdfd5c5
3 changed files with 96 additions and 7 deletions
+12 -6
View File
@@ -502,7 +502,7 @@
MODE TOGGLES (Add Asset tab)
═══════════════════════════════════════════════════════════════════════ */
.mode-toggles {
display: flex; gap: 4px; margin-bottom: 10px;
display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 10px;
background: var(--card2); border-radius: var(--radius-sm); padding: 4px;
}
.mode-toggle {
@@ -1725,6 +1725,9 @@
// Extract EXIF / file metadata
extractExifData(file);
// Auto-extract GPS from the picked photo
tryExtractGpsFromPicked();
// Scroll to preview
document.getElementById('photoPreviewCard').scrollIntoView({ behavior: 'smooth' });
};
@@ -2467,7 +2470,7 @@
// MANUAL MODE — Photo
// ═══════════════════════════════════════════════════════════════════════
let manualPhotoFile = null;
let manualPhotoBlob = null;
manualPhotoBlob = null; // reuse existing declaration
let manualPhotoGps = null;
async function handleManualPhotoFile(event) {
@@ -2524,13 +2527,16 @@
if (manualPhotoFile) {
try {
const fd = new FormData();
// Read EXIF before upload (defense against transport stripping)
try {
const exifData = await exifr.parse(manualPhotoFile);
if (exifData && Object.keys(exifData).length > 0) {
fd.append('exif_data', JSON.stringify(exifData));
}
} catch (_) { /* EXIF extraction is best-effort */ }
fd.append('file', manualPhotoFile, manualPhotoFile.name || 'photo.jpg');
const upData = await api('/api/upload/photo', { method: 'POST', body: fd });
photoPath = upData.path;
// If server returned EXIF GPS and we don't have GPS from the file yet, use it
if (upData.exif_gps && !manualPhotoGps) {
manualPhotoGps = upData.exif_gps;
}
} catch (e) { /* photo upload failed, continue without */ }
}