Zum Hauptinhalt springen

File Storage — Setup & Deployment

Voraussetzungen​

Das File-Storage-System ist vollständig implementiert und produktiv. Code, Dependency und Migration sind bereits Teil des Repositories:

BereichInhaltStatus
Schema & MigrationPrisma Schema, Migration 20251128215910_add_file_storage (eingespielt)Abgeschlossen
Dependency@vercel/blob ^2.3.1 in package.jsonInstalliert
Storage-LayerTypeScript Interfaces, Vercel Blob Provider, Storage Factory, File ValidationAbgeschlossen
ServicesUpload Service, Download Service, Permission ServiceAbgeschlossen
API-RoutesUpload, Download, Public, List, AdminAbgeschlossen
DSGVO Cron-Jobsvercel.json-Konfiguration aktivAbgeschlossen
FrontendFileUploadDialog, FileListAbgeschlossen
DokumentationArchitektur + SetupAbgeschlossen

Da Code und Migration bereits vorhanden sind, beschränkt sich das Setup einer neuen Umgebung auf das Setzen der Secrets (Blob-Token und Cron-Secret).


Schritt-für-Schritt Setup (neue Umgebung)​

Dependency-Installation und Prisma-Migration sind bereits Teil des Repositories — beim regulären pnpm install / pnpm initdb werden sie automatisch übernommen. Für ein frisches Setup genügt:

pnpm install        # installiert u. a. @vercel/blob
pnpm initdb # spielt Migrationen (inkl. add_file_storage) ein und seedet

1. Vercel Blob Store erstellen​

1.1 Blob Store anlegen​

  1. Vercel Dashboard öffnen
  2. Projekt auswählen
  3. Storage (linke Sidebar) anklicken
  4. Create Database anklicken
  5. Blob → Continue auswählen
  6. Region: Frankfurt (eu-central-1)
  7. Create anklicken

1.2 Token generieren​

  1. Den neuen Blob Store anklicken
  2. Settings Tab öffnen
  3. Zu Tokens scrollen
  4. Generate Token anklicken
  5. Name: File Storage Read/Write
  6. Permissions: Read and Write aktivieren
  7. Create anklicken
  8. Wichtig: Token sofort kopieren — er wird nur einmal angezeigt

1.3 Token in Vercel setzen​

  1. Im Projekt: Settings → Environment Variables
  2. Add New anklicken
  3. Name: BLOB_READ_WRITE_TOKEN
  4. Value: vercel_blob_rw_... (generierter Token)
  5. Environments: Production, Preview, Development aktivieren
  6. Save anklicken

2. Cron Secret generieren​

Windows PowerShell:

[Convert]::ToBase64String((1..32 | ForEach-Object { Get-Random -Minimum 0 -Maximum 256 }))

Linux/Mac:

openssl rand -base64 32

Den generierten String in Vercel als Environment-Variable setzen:

  1. Settings → Environment Variables
  2. Add New anklicken
  3. Name: CRON_SECRET
  4. Value: generierter String
  5. Environments: Production, Preview aktivieren
  6. Save anklicken

3. Environment Variables lokal setzen​

Die lokale Umgebung lädt .env (im Verzeichnis webapp/). Datei erstellen oder erweitern:

# File Storage
BLOB_READ_WRITE_TOKEN=vercel_blob_rw_...
BLOB_PRIVATE_READ_WRITE_TOKEN=vercel_blob_rw_...
FILE_ENCRYPTION_KEY=<openssl rand -base64 32>
CRON_SECRET=<generiertes-secret>

# Optional: Größenlimits (nur bei Vercel Pro sinnvoll — siehe Abschnitt Hobby-Plan)
# FILE_MAX_SIZE_IMAGE=10485760 # 10MB
# FILE_MAX_SIZE_PDF=26214400 # 25MB

Sicherstellen, dass .env über das Repository-.gitignore (webapp/.env*) ausgeschlossen ist und der Token nicht committed wird.


4. Deployment verifizieren​

Im Vercel Dashboard unter Deployments:

  • Status muss Ready sein
  • Build-Logs dürfen keine Fehler zeigen

Cron-Jobs prüfen (im Projekt-Dashboard unter Cron Jobs):

PfadScheduleStatus
/api/cron/check-expired-files0 2 * * * (täglich 2:00 Uhr)Active
/api/cron/delete-non-critical-files0 3 * * * (täglich 3:00 Uhr)Active

Falls Cron-Jobs nicht angezeigt werden: sicherstellen, dass vercel.json committed ist, dann Re-Deploy mit vercel --prod.


Environment Variables​

Required​

VariableBeschreibung
BLOB_READ_WRITE_TOKENToken des öffentlichen Stores (Format: vercel_blob_rw_...)
BLOB_PRIVATE_READ_WRITE_TOKENToken des privaten Stores
FILE_ENCRYPTION_KEYHauptschlüssel, 32 Bytes als Base64. In der Preview: DEVELOP_FILE_ENCRYPTION_KEY. Siehe Dateischutz
CRON_SECRETGeheimnis zur Authentifizierung der Cron-Job-Endpunkte

Optional (mit Standardwerten)​

VariableStandardBeschreibung
FILE_MAX_SIZE_IMAGE4000000Maximale Bildgröße in Bytes (4 MB, Hobby-Plan)
FILE_MAX_SIZE_PDF4000000Maximale PDF-Größe in Bytes (4 MB, Hobby-Plan)
RETENTION_STUDENT_DOCS3650Aufbewahrungsdauer Schülerdokumente in Tagen (10 Jahre)
RETENTION_PROFILE_IMAGE730Aufbewahrungsdauer Profilbilder in Tagen (2 Jahre)

Vercel Hobby-Plan Einschränkungen​

Der Vercel Hobby-Plan hat ein Payload-Limit von 4,5 MB pro Request. Für Datei-Uploads bedeutet das:

  • Maximale Dateigröße: 4 MB
  • FILE_MAX_SIZE_IMAGE und FILE_MAX_SIZE_PDF müssen auf 4000000 gesetzt bleiben

Was funktioniert​

DateitypTypische GrößeStatus
Zeugnisse~500 KBFunktioniert
Bescheinigungen~200 KBFunktioniert
Profilbilder~1 MBFunktioniert
Standard-PDFs~2 MBFunktioniert

Was nicht funktioniert​

  • Große PDFs mit vielen Seiten (> 4 MB)
  • Hochauflösende Scans (> 4 MB)
  • Große Bilddateien (> 4 MB)

Das Frontend zeigt eine Warnung an, wenn eine Datei das Limit überschreitet.

Upgrade-Optionen​

Option A: Vercel Pro (empfohlen bei ausreichendem Budget)

  • Kosten: $20/Monat
  • Payload-Limit: 50 MB
  • Einfachste Lösung

Option B: Direct-Upload (kostenlos, aber aufwendiger)

  • Browser uploaded direkt zu Vercel Blob, umgeht das Next.js Payload-Limit
  • Erfordert zusätzliche Implementierung
  • Für den aktuellen Einsatzbereich (Schuldokumente < 4 MB) nicht erforderlich

Troubleshooting​

"BLOB_READ_WRITE_TOKEN is not set"​

  1. Vercel Dashboard → Settings → Environment Variables prüfen — ist der Token gesetzt?
  2. Re-Deploy ausführen
  3. Für lokale Entwicklung: .env prüfen

Upload schlägt fehl​

Häufige Ursachen:

  • Datei ist größer als 4 MB (Hobby-Plan Limit)
  • Falscher Dateityp (z. B. .exe)
  • Token fehlt oder ist falsch

Diagnose:

  1. Browser-Konsole öffnen (F12) und Fehlerdetails lesen
  2. Vercel Logs prüfen
  3. Dateigröße reduzieren
  4. Token überprüfen

Cron-Jobs nicht sichtbar​

  1. Ist vercel.json committed? (git log --oneline -1 prüfen)
  2. Re-Deploy ausführen: vercel --prod
  3. 1–2 Minuten warten, Dashboard neu laden

TypeScript-Fehler nach Migration​

npx prisma generate
pnpm typecheck

Wenn Fehler weiterhin bestehen:

rm -rf node_modules .next
pnpm install
pnpm build

Migration schlägt fehl​

# Schema prüfen
npx prisma format

# Migration Reset — ACHTUNG: löscht alle Daten!
npx prisma migrate reset

# Migration neu ausführen
npx prisma migrate dev

Cron-Job manuell testen​

curl -X GET "https://<domain>.vercel.app/api/cron/check-expired-files" \
-H "Authorization: Bearer <cron-secret>"

Erwartete Antwort:

{
"success": true,
"markedCount": 0,
"timestamp": "..."
}

Nach dem Setup​

Verifikations-Checkliste​

Bereits im Repository enthalten (kein manueller Schritt nötig):

  • @vercel/blob (^2.3.1) installiert
  • Migration 20251128215910_add_file_storage vorhanden
  • Cron-Jobs in vercel.json registriert

Pro Umgebung zu prüfen:

  • Vercel Blob Store erstellt
  • BLOB_READ_WRITE_TOKEN in Vercel und in .env gesetzt
  • Privater Blob Store erstellt, BLOB_PRIVATE_READ_WRITE_TOKEN in Vercel und in .env gesetzt
  • FILE_ENCRYPTION_KEY je Umgebung gesetzt, Kopie außerhalb von Vercel gesichert
  • CRON_SECRET in Vercel und in .env gesetzt
  • Deployment-Status: Ready
  • Cron-Jobs im Dashboard aktiv
  • Test-Upload erfolgreich
  • Test-Download erfolgreich
  • Datei im Blob Store sichtbar (Vercel Dashboard → Storage → Blob Store)

Nächste Schritte​

Frontend-Integration — FileUpload in bestehende Seiten einbinden:

import { FileUploadDialog } from '@/components/file/FileUploadDialog';
import { FileList } from '@/components/file/FileList';

<FileList studentId={params.id} category="STUDENT_DOCUMENT" />

<FileUploadDialog
open={uploadOpen}
onOpenChange={setUploadOpen}
onUploadComplete={() => refetch()}
defaultCategory="STUDENT_DOCUMENT"
studentId={params.id}
/>

Admin-Page — Datei anlegen unter app/admin/files/page.tsx für zentrales File-Management.

Mittelfristig:

  • Unit-Tests und E2E-Tests für Upload/Download/Permissions schreiben
  • Monitoring über Vercel Analytics aktivieren
  • Storage-Verbrauch überwachen (Vercel Dashboard → Storage)
  • Backup-Strategie evaluieren (Vercel Blob hat kein Auto-Backup)