File Upload API
Test-Zugangsdaten
| Feld | Wert |
|---|---|
demo@iab.de | |
| Password | winter123456 |
Nach den Migrationen kann der Administrator deterministisch angelegt oder aktualisiert werden:
php artisan migrate
./bin/make-demo-admin.sh
Das Skript ist idempotent. Ein bestehender Account mit demo@iab.de behaelt seine ID und seinen Namen, erhaelt aber erneut Administratorrechte und das oben dokumentierte Passwort.
Authentication
Alle Verwaltungsendpunkte unter /api/files erfordern einen Bearer-Token. Die oeffentlichen Leseendpunkte unter /api/public/files benoetigen keinen Token. Token anfordern via:
POST /api/tokens
Content-Type: application/json
{
"email": "demo@iab.de",
"password": "winter123456",
"token_name": "my-client"
}
Response 201 Created
{ "token": "1|xxxxxxxxxxxx" }
Token widerrufen:
DELETE /api/tokens/current
Authorization: Bearer <token>
Response 204 No Content
Berechtigungen
- Normale Benutzer koennen nur eigene Dateien auflisten, lesen, aktualisieren, ersetzen, herunterladen und loeschen. Zugriffe auf fremde IDs liefern
404. - Administratoren koennen Dateien aller Benutzer und unabhaengig von
freigabeverwalten. - Administratoren koennen auch unveroeffentlichte oder noch gesperrte Inhalte herunterladen.
- Die Administratorrolle wird nicht ueber die HTTP-API vergeben. Dafuer dient
./bin/make-demo-admin.sh.
Endpoints
CRUD-Uebersicht
| Operation | HTTP | Endpoint | Beschreibung |
|---|---|---|---|
| Create | POST | /api/files | Eine oder mehrere Dateien hochladen |
| Read (List) | GET | /api/files | Erlaubte Dateien paginiert auflisten |
| Read (Single) | GET | /api/files/{id} | Metadaten einer einzelnen Datei lesen |
| Download | GET | /api/files/{id}/download | Dateiinhalt herunterladen |
| Update | PATCH | /api/files/{id} | Metadaten (und optional path) aktualisieren |
| Replace Content | POST | /api/files/{id}/content | Dateiinhalt unter derselben ID ersetzen |
| Delete | DELETE | /api/files/{id} | Datei inkl. Metadaten loeschen |
Datei erstellen (Create)
POST /api/files
Authorization: Bearer <token>
Content-Type: multipart/form-data
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
files[] | File(s) | ja | 1–25 Dateien, je max. 200 MB |
path | string | nein | Virtueller Zielpfad, z. B. projekte/2026/q1 |
aktiv_id | string | nein | Externe Aktivitäts- oder Vorgangsnummer |
reprotyp | string | nein | Repräsentationstyp, z. B. forschungsbericht |
titel | string | nein | Titel der Datei/Publikation |
beschreibung | string | nein | Kurzbeschreibung (max. 5000 Zeichen) |
autoren | string | nein | Autorenangabe(n) |
sachschlagwoerter | string | nein | Sachschlagwörter |
iab_themen | string | nein | IAB-Themenbereich |
sperrfrist | date | nein | Sperrdatum (YYYY-MM-DD), Download bis dahin gesperrt |
reihenfolge | integer | nein | Sortierreihenfolge (default: 0) |
freigabe | boolean | nein | Ob die Datei abrufbar ist (default: true) |
erstellt_von | string | nein | Freie Angabe zur erstellenden Person oder Stelle |
freigegeben_von | string | nein | Freie Angabe zur freigebenden Person oder Stelle |
Der path definiert die Ordnerstruktur. Erlaubte Zeichen: a-z A-Z 0-9 . _ - und / als Trennzeichen. Kein führender oder abschließender Slash, keine ..-Segmente.
Beispiel
curl -X POST https://repo.iab.de/api/files \
-H "Authorization: Bearer <token>" \
-F "files[]=@bericht.pdf" \
-F "files[]=@daten.xlsx" \
-F "path=projekte/2026/q1"
Response 201
{
"files": [
{
"id": "018f1a2b-...",
"aktiv_id": "AKT-2026-001",
"original_name": "bericht.pdf",
"path": "projekte/2026/q1",
"mime_type": "application/pdf",
"size": 204800,
"reprotyp": "forschungsbericht",
"titel": "Arbeitsmarktbericht 2026",
"beschreibung": null,
"autoren": "Max Mustermann",
"sachschlagwoerter": null,
"iab_themen": null,
"sperrfrist": null,
"reihenfolge": 0,
"freigabe": true,
"erstellt_von": "Redaktion Dashboard",
"freigegeben_von": "Admin Dashboard",
"created_at": "2026-04-30T10:00:00.000000Z"
}
]
}
Datei herunterladen
GET /api/files/{id}/download
Authorization: Bearer <token>
Liefert die Datei als Download mit korrektem Content-Type und originalem Dateinamen. Normale Benutzer koennen nur eigene Dateien herunterladen (sonst 404). Bei freigabe=false oder sperrfrist in der Zukunft folgt fuer normale Benutzer 403; Administratoren duerfen diese Inhalte herunterladen.
Bei Audio-Dateien wird der server-seitig erkannte MIME-Typ im Content-Type des Downloads verwendet. Der Dateiinhalt wird beim Upload, Download und beim Ersetzen des Inhalts nicht umgewandelt. Je nach fileinfo-Erkennung kann eine WAV-Datei als audio/x-wav, audio/wav oder audio/wave gespeichert werden. OGG wird als audio/ogg und MP3 als audio/mpeg gespeichert.
curl -OJ "https://repo.iab.de/api/files/018f1a2b-.../download" \
-H "Authorization: Bearer <token>"
Datei lesen (Read Single)
GET /api/files/{id}
Authorization: Bearer <token>
Gibt die Metadaten einer einzelnen erlaubten Datei zurueck. Normale Benutzer sehen nur eigene, Administratoren alle Datensaetze, auch bei freigabe=false.
Response 200
{
"id": "018f1a2b-...",
"aktiv_id": "AKT-2026-001",
"original_name": "bericht.pdf",
"path": "projekte/2026/q1",
"mime_type": "application/pdf",
"size": 204800,
"reprotyp": "forschungsbericht",
"titel": "Arbeitsmarktbericht 2026",
"beschreibung": null,
"autoren": "Max Mustermann",
"sachschlagwoerter": null,
"iab_themen": null,
"sperrfrist": null,
"reihenfolge": 0,
"freigabe": true,
"erstellt_von": "Redaktion Dashboard",
"freigegeben_von": "Admin Dashboard",
"created_at": "2026-04-30T10:00:00.000000Z",
"updated_at": "2026-04-30T10:00:00.000000Z"
}
curl "https://repo.iab.de/api/files/018f1a2b-..." \
-H "Authorization: Bearer <token>"
Dateien auflisten
GET /api/files
Authorization: Bearer <token>
Gibt fuer normale Benutzer alle eigenen Uploads und fuer Administratoren die Uploads aller Benutzer zurueck. Die Liste ist nach Hochladezeitpunkt sortiert (neueste zuerst) und auf 100 Eintraege pro Seite paginiert. Mit freigabe=0 kann das Admin-Dashboard gezielt unveroeffentlichte Datensaetze abrufen.
Optionale Filter (kombinierbar):
| Parameter | Beschreibung | Beispiel |
|---|---|---|
path | Pfad-Präfix | path=projekte/2026 |
aktiv_id | Exakte Aktivitäts-ID | aktiv_id=AKT-2026-001 |
since | Nur Dateien ab diesem Zeitpunkt | since=2026-04-30T12:00:00%2B02:00 |
freigabe | Nach Freigabe filtern | freigabe=1 oder freigabe=0 |
reprotyp | Nach Repräsentationstyp filtern | reprotyp=forschungsbericht |
since – Zeitpunkt mit Zeitzone
Der Wert muss ISO 8601 sein. Ohne Offset wird UTC angenommen – bei lokaler Zeit (z. B. Europe/Berlin, CEST = UTC+2) immer den Offset mitsenden:
# Alle Uploads seit 30. April 12:00 Uhr Berliner Zeit
curl "https://repo.iab.de/api/files?since=2026-04-30T12:00:00%2B02:00" \
-H "Authorization: Bearer <token>"
# Alternativ direkt als UTC
curl "https://repo.iab.de/api/files?since=2026-04-30T10:00:00Z" \
-H "Authorization: Bearer <token>"
curl "https://repo.iab.de/api/files?aktiv_id=AKT-2026-001" \
-H "Authorization: Bearer <token>"
curl "https://repo.iab.de/api/files?path=projekte/2026" \
-H "Authorization: Bearer <token>"
Datei aktualisieren (Update)
PATCH /api/files/{id}
Authorization: Bearer <token>
Content-Type: application/json
Aktualisiert Metadaten einer bestehenden eigenen Datei. Es werden nur uebergebene Felder geaendert (partielles Update). Optional kann auch path geaendert werden.
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
path | string | nein | Neuer virtueller Zielpfad |
aktiv_id | string | nein | Externe Aktivitaets- oder Vorgangsnummer |
reprotyp | string | nein | Repraesentationstyp |
titel | string | nein | Titel der Datei/Publikation |
beschreibung | string | nein | Kurzbeschreibung (max. 5000 Zeichen) |
autoren | string | nein | Autorenangabe(n) |
sachschlagwoerter | string | nein | Sachschlagwoerter |
iab_themen | string | nein | IAB-Themenbereich |
sperrfrist | date | nein | Sperrdatum (YYYY-MM-DD) |
reihenfolge | integer | nein | Sortierreihenfolge |
freigabe | boolean | nein | Ob die Datei abrufbar ist |
erstellt_von | string | nein | Erstellende Person oder Stelle |
freigegeben_von | string | nein | Freigebende Person oder Stelle |
curl -X PATCH "https://repo.iab.de/api/files/018f1a2b-..." \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"titel": "Arbeitsmarktbericht 2026 (final)",
"freigabe": true,
"reihenfolge": 10
}'
Response 200
{
"id": "018f1a2b-...",
"titel": "Arbeitsmarktbericht 2026 (final)",
"freigabe": true,
"reihenfolge": 10,
"updated_at": "2026-05-01T09:15:00.000000Z"
}
Dateiinhalt ersetzen
POST /api/files/{id}/content
Authorization: Bearer <token>
Content-Type: multipart/form-data
Ersetzt nur den gespeicherten Inhalt einer Datei. Die Datensatz-ID, der Besitzer, created_at und alle Fachmetadaten bleiben erhalten. Aktualisiert werden original_name, stored_path, mime_type, size und updated_at. Nach erfolgreicher Aktualisierung wird der alte Inhalt geloescht.
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
file | File | ja | Neue Datei, maximal 200 MB |
curl -X POST "https://repo.iab.de/api/files/018f1a2b-.../content" \
-H "Authorization: Bearer <token>" \
-F "file=@daten-korrigiert.csv"
Response 200: Vollstaendige Metadaten des bestehenden Datensatzes mit unveraenderter id und aktualisiertem updated_at.
Datei löschen
DELETE /api/files/{id}
Authorization: Bearer <token>
Loescht Datei und Metadaten-Eintrag. Normale Benutzer koennen nur eigene Dateien loeschen (sonst 404), Administratoren auch fremde Dateien.
Oeffentliche Lese-API
Die folgenden Endpunkte sind ohne Token erreichbar. Sie liefern ausschliesslich Datensaetze mit freigabe=true; ein Query-Parameter kann diese Einschraenkung nicht umgehen.
| HTTP | Endpoint | Beschreibung |
|---|---|---|
GET | /api/public/files | Freigegebene Metadaten paginiert auflisten |
GET | /api/public/files/{id} | Freigegebene Metadaten einzeln lesen |
GET | /api/public/files/{id}/download | Freigegebenen Dateiinhalt herunterladen |
Die Liste unterstuetzt die Filter path, aktiv_id, since und reprotyp wie die geschuetzte Liste. Eine zukuenftige sperrfrist versteckt die Metadaten nicht, blockiert aber den oeffentlichen Download mit 403. Unveroeffentlichte IDs liefern bei Einzelansicht und Download 404.
Die oeffentlichen JSON-Antworten enthalten updated_at, damit Clients ersetzte Inhalte erkennen koennen. Interne Felder wie user_id, stored_path, erstellt_von und freigegeben_von werden nicht ausgegeben. Antworten setzen Cache-Control: public, max-age=0, must-revalidate.
curl "https://repo.iab.de/api/public/files?reprotyp=datensatz"
curl -OJ "https://repo.iab.de/api/public/files/018f1a2b-.../download"
Erlaubte Dateitypen
| Extension | MIME Type |
|---|---|
pdf | application/pdf |
txt | text/plain |
csv | text/csv |
jpg / jpeg | image/jpeg |
png | image/png |
gif | image/gif |
webp | image/webp |
doc | application/msword |
docx | application/vnd.openxmlformats-officedocument.wordprocessingml.document |
xlsx | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet |
pptx | application/vnd.openxmlformats-officedocument.presentationml.presentation |
zip | application/zip |
mp4 | video/mp4 |
wav | audio/x-wav, audio/wav, audio/wave |
ogg | audio/ogg |
mp3 | audio/mpeg |
rdf | application/rdf+xml |
json | application/json |
Der MIME-Typ wird server-seitig anhand der Datei-Magic-Bytes geprüft, nicht anhand des Client-Headers.
Limits
| Parameter | Wert |
|---|---|
| Max. Dateien pro Request | 25 |
| Max. Dateigröße | 200 MB |
Fehler
| Code | Bedeutung |
|---|---|
401 | Kein oder ungültiger Token |
403 | Download fuer normalen/oeffentlichen Zugriff gesperrt |
404 | Datei nicht gefunden oder gehört anderem Nutzer |
413 | Request Entity Too Large (typisch nginx vor der API, z. B. client_max_body_size) |
422 | Validierungsfehler (Dateityp, Größe, ungültiger Pfad, ungültige Update-Felder/Werte) |
Beispiel Validierungsfehler
{
"message": "The files.0 field must be a file of type: pdf, txt, ...",
"errors": {
"files.0": ["Unsupported file type."]
}
}
Speicherstruktur
Dateien werden privat gespeichert (nicht öffentlich erreichbar) unter:
storage/app/private/uploads/{user_id}/{YYYY}/{MM}/{DD}/{hashname}
Der virtuelle Metadatenwert path beeinflusst den physischen Speicherpfad nicht. Der Dateiname wird als eindeutiger Hash gespeichert:
storage/app/private/uploads/1/2026/04/30/aB3xYz9kQ2mN4pR7.pdf