# Streaming-Implementationsliste (Option 2) – Storage Modul Ziel: Dedizierte Streaming-Methoden in der Object Storage API implementieren – ohne externe Dependencies. Fokus auf speichereffiziente Downloads/Uploads großer Dateien via Streams (memory-safe). ## 1) Interface-Erweiterung (ObjectStorage) - Ergänze folgende Methoden im ObjectStorage-Interface: - get(string $bucket, string $key): string - put(string $bucket, string $key, string|mixed $body, array $opts = []): ObjectInfo - getToStream(string $bucket, string $key, mixed $destination): int - Erwartet eine schreibbare PHP-Stream-Resource als $destination - Rückgabewert: Anzahl geschriebener Bytes - putFromStream(string $bucket, string $key, mixed $source, array $opts = []): ObjectInfo - Erwartet eine lesbare PHP-Stream-Resource als $source - openReadStream(string $bucket, string $key) - Gibt eine lesbare PHP-Stream-Resource zurück - head(string $bucket, string $key): ObjectInfo - delete(string $bucket, string $key): void - exists(string $bucket, string $key): bool - url(string $bucket, string $key): ?string - temporaryUrl(string $bucket, string $key, \DateInterval $ttl, array $opts = []): string Hinweise: - Signaturen mit mixed für Stream-Parameter (PHP-Resource), genaue Validierung in den Implementierungen. - Bestehende Methoden get/put bleiben kompatibel; Streaming ist ergänzend. ## 2) Filesystem-Adapter (lokales Backend) Ziel: ObjectStorage-Implementierung auf Basis des bestehenden Filesystem-Backends. - Neue Klasse: src/Framework/Storage/FilesystemObjectStorage.php - Verantwortlichkeiten: - Pfadaufbau: basePath/bucket/key - get/put über Filesystem (kleine Dateien) - Streaming: - getToStream: Datei lesen und via stream_copy_to_stream in $destination schreiben - putFromStream: Stream-Inhalt in Datei schreiben (Chunked Copy) - openReadStream: lesbaren Stream auf die Datei öffnen - head/exists/delete/url/temporaryUrl: - head: Dateigröße, mtime, mimetype (falls verfügbar) - url: für lokales Storage in der Regel null (oder optionaler lokaler URL-Generator) - temporaryUrl: nicht unterstützt -> Exception oder leer lassen mit Doku - Fehlerbehandlung: - File not found, Permission, Read/Write-Errors sauber abbilden - Performance: - Buffersize bei stream_copy_to_stream kontrollierbar machen (Optionen) ## 3) MinIO-Backend (ohne Dependencies) Ziel: S3-kompatibler MinIO-Client mittels nativer PHP-Funktionen (HTTP-Streams und AWS SigV4) + ObjectStorage-Adapter. - Dateien: - src/Framework/Storage/Clients/MinioClient.php - Funktionen: putObject, getObject, headObject, deleteObject, createPresignedUrl - Streaming-Funktionen: - getObjectToStream($bucket, $key, $destination): int - putObjectFromStream($bucket, $key, $source, array $opts = []): array - openStream($bucket, $key) -> resource - Interne Helfer: - AWS SigV4 Signierung (kanonische Anfrage, Header, Query, Hashes) - Response-Parsing (Headers, Status, Fehler-XML) - Chunked Transfer wenn keine Content-Length verfügbar - src/Framework/Storage/MinioObjectStorage.php - Implementiert ObjectStorage - get/put: kleinere Dateien - getToStream/putFromStream/openReadStream: nutzen die Streaming-APIs des MinioClient - head/delete/exists/url/temporaryUrl: - temporaryUrl via createPresignedUrl - Sicherheit: - TTL-Limits für temporaryUrl (z. B. max 24h) - Path-Style vs. Virtual Host Style konfigurierbar - Keine externen Pakete ## 4) Manager/Factory/DI - Option A: StorageManager für ObjectStorage-Driver (local/minio) - src/Framework/Storage/StorageManager.php - driver(string $name): ObjectStorage - bucket(string $name): Bucket (Convenience) - Option B (einfach): Container-Bindings direkt - Default ObjectStorage anhand ENV - Initializer: - src/Framework/Storage/StorageInitializer.php - Konfig aus ENV (DEFAULT_DRIVER, MINIO_ENDPOINT, KEYS, LOCAL_ROOT, PATH_STYLE etc.) - Registriere: - FilesystemObjectStorage (als "local") - MinioClient + MinioObjectStorage (als "minio") - ObjectStorage (Default: ENV) - Bucket-API (optional aber DX-freundlich): - src/Framework/Storage/Bucket.php - wrappt ObjectStorage für festen Bucket-Namen ## 5) Konfiguration - ENV Variablen vorschlagen (Beispiele): - STORAGE_DRIVER=local|minio - STORAGE_LOCAL_ROOT=/var/www/html/storage/objects - MINIO_ENDPOINT=http://minio:9000 - MINIO_ACCESS_KEY=... - MINIO_SECRET_KEY=... - MINIO_REGION=us-east-1 - MINIO_USE_PATH_STYLE=true - StorageConfig Klasse (optional) für strukturierte Konfig-Verwaltung ## 6) Tests (kritisch, da streaming-sensitiv) - Unit-Tests FilesystemObjectStorage: - put/get mit Strings - putFromStream/getToStream mit temp Streams (php://temp) - openReadStream und sequentielles Lesen - head/exists/delete - Unit-Tests MinioClient (Signierung) – isoliert: - Signatur-Konsistenz (Golden Master) - Parsing von Fehlern/Headers - Integration-Tests (optional, per docker-compose mit MinIO): - Upload/Download großer Dateien (z. B. >100MB) per Streams - temporaryUrl Zugriff (GET) mit TTL - Edge Cases: - fehlende Read-/Write-Berechtigungen (Filesystem) - Netzwerkfehler (MinIO) - Nicht existierende Objekte - Streams ohne bekannte Länge (Chunked Transfer) ## 7) Fehler- und Ausnahmebehandlung - Konsistente Exceptions im Storage-Namespace (z. B. StorageException) - Filesystem-spezifische Fehler sauber mappen - Aussagekräftige Meldungen (inkl. Pfad/Bucket/Key) ## 8) Performance/Robustheit - Stream-Buffer konfigurierbar (z. B. 8192 Bytes Default) - Keine vollständigen Dateiladungen in Memory bei Streams - Zeitouts/Retry-Strategie (MinIO) minimal vorsehen (optional) - Sauberes Schließen aller Streams (try/finally) ## 9) Sicherheit - Path-Sanitizing im Filesystem-Adapter (keine Directory-Traversal) - Eindeutige Handhabung von public URL vs. presigned URL - Limitierung der Presign-Dauer und Validierung von Eingaben ## 10) Dokumentation - README/HowTo: - Beispiel für lokale und MinIO-Nutzung - Beispiele für Streaming (Upload/Download) - Hinweise zu großen Dateien, Memory-Effizienz - PHPDoc ausführlich an allen Public-APIs ## 11) Milestones (Reihenfolge) 1. Interface-Änderungen (ObjectStorage) 2. FilesystemObjectStorage (inkl. Streaming) 3. MinioClient (Basis + Signierung) 4. MinioObjectStorage (inkl. Streaming) 5. Initializer/DI und Konfig 6. Tests (Unit), danach optional Integration 7. Doku + Beispiele ## 12) Definition of Done - Alle neuen Methoden implementiert und getestet - Große Dateien via Streams funktionieren, ohne OOM - Kein externer Dependency-Einsatz - Doku und Beispiele vorhanden - CI-Tests grün (Unit; Integration optional)