revert(admin): Knopf zum Neuerzeugen der Vorschaubilder wieder raus
130 Zeilen fuer einen einmaligen Bedarf - die Haelfte davon eine Karte im Admin-Bereich, die sonst dauerhaft dort steht. Die EXIF-Behebung selbst bleibt: Neu hochgeladene Bilder stehen richtig herum. Bestehende Vorschaubilder werden damit nicht mehr nachgezogen. Wer sie gerade ruecken will, laedt die Datei erneut hoch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4bd9a6ca56
commit
5b3658640e
6 files changed
+7
-166
No files matched your search
@@ -529,9 +529,6 @@ func main() {
|
||||
r.Get("/admin/audit", adminHandler.ListAudit)
|
||||
r.Get("/admin/audit/actions", adminHandler.ListAuditActions)
|
||||
r.Post("/admin/gc", adminHandler.RunGC)
|
||||
// Vorschaubilder neu erzeugen – nötig für alles, was vor der
|
||||
// Auswertung der EXIF-Drehung hochgeladen wurde.
|
||||
r.Post("/admin/thumbnails/rebuild", adminHandler.RebuildThumbnails)
|
||||
// Immer erreichbar, auch wenn OCR aus ist – der Handler antwortet dann
|
||||
// mit enabled:false. Eine Route, die je nach Konfiguration 404 liefert,
|
||||
// wäre für die Oberfläche nicht von einem Fehler zu unterscheiden.
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"aether/internal/audit"
|
||||
"aether/internal/thumbnails"
|
||||
"aether/pkg/response"
|
||||
)
|
||||
|
||||
/*
|
||||
POST /api/v1/admin/thumbnails/rebuild – Vorschaubilder neu erzeugen.
|
||||
|
||||
Anlass: Bis heute wurde die EXIF-Drehung beim Erzeugen nicht ausgewertet.
|
||||
Jedes hochkant aufgenommene Foto liegt im bestehenden Bestand deshalb quer,
|
||||
während dasselbe Bild in der großen Ansicht aufrecht steht – der Browser
|
||||
befolgt die Notiz von selbst, der Server tat es nicht.
|
||||
|
||||
Beim Hochladen entstehen Vorschaubilder von allein; für das, was schon da ist,
|
||||
braucht es diesen einen Anstoß. Er läuft im Vordergrund und meldet Zahlen:
|
||||
Ein Vorgang, der den halben Bestand neu schreibt, soll nicht stumm im
|
||||
Hintergrund verschwinden.
|
||||
*/
|
||||
func (h *Handler) RebuildThumbnails(w http.ResponseWriter, r *http.Request) {
|
||||
if _, ok := requireAdmin(r); !ok {
|
||||
response.Error(w, http.StatusForbidden, "admin required")
|
||||
return
|
||||
}
|
||||
|
||||
list, err := h.files.ImageFiles(r.Context())
|
||||
if err != nil {
|
||||
response.Error(w, http.StatusInternalServerError, "could not list images")
|
||||
return
|
||||
}
|
||||
|
||||
var rebuilt, failed int
|
||||
for _, f := range list {
|
||||
if !thumbnails.SupportedMIME(f.MimeType) {
|
||||
continue
|
||||
}
|
||||
rc, err := h.storage.Get(r.Context(), f.StorageKey)
|
||||
if err != nil {
|
||||
failed++
|
||||
continue
|
||||
}
|
||||
err = thumbnails.Generate(r.Context(), h.storage, f.ID.String(), f.MimeType, rc)
|
||||
rc.Close()
|
||||
if err != nil {
|
||||
failed++
|
||||
continue
|
||||
}
|
||||
// Auch setzen, wenn es schon stand: Dateien, bei denen die Erzeugung
|
||||
// beim Hochladen fehlschlug, bekommen so nachträglich eines.
|
||||
if err := h.files.UpdateThumbnail(r.Context(), f.ID, true); err != nil {
|
||||
failed++
|
||||
continue
|
||||
}
|
||||
rebuilt++
|
||||
}
|
||||
|
||||
h.logAdmin(r, audit.ActionGarbageCollect, "storage", "", "",
|
||||
fmt.Sprintf("thumbnails rebuilt: %d of %d images, %d failed",
|
||||
rebuilt, len(list), failed))
|
||||
|
||||
response.JSON(w, http.StatusOK, map[string]any{
|
||||
"images": len(list),
|
||||
"rebuilt": rebuilt,
|
||||
"failed": failed,
|
||||
})
|
||||
}
|
||||
@@ -533,29 +533,3 @@ func isUniqueViolation(err error) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ImageFiles nennt alle nicht gelöschten Dateien, aus denen ein Vorschaubild
|
||||
// entstehen kann – für das Neuerzeugen von Hand.
|
||||
//
|
||||
// Ohne Papierkorb: Für eine Datei, die man weggeworfen hat, lohnt keine Runde
|
||||
// durch den Dekodierer.
|
||||
func (s *Store) ImageFiles(ctx context.Context) ([]*File, error) {
|
||||
rows, err := s.db.Query(ctx,
|
||||
`SELECT `+fileCols+`
|
||||
FROM files
|
||||
WHERE is_deleted = false AND mime_type LIKE 'image/%'
|
||||
ORDER BY created_at`)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("query image files: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []*File
|
||||
for rows.Next() {
|
||||
var f File
|
||||
if err := scanFile(rows, &f); err != nil {
|
||||
return nil, fmt.Errorf("scan image file: %w", err)
|
||||
}
|
||||
out = append(out, &f)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
Reference in new issue
Block a user