Zip in PHP direkt nach String auspacken?

OP (Firma: Q3) #6229239
Lesenswert?

Ich könnte es auch einfach ausprobieren, aber vlt. weiss das hier jemand 
aus dem Stand und ich spare etwas Zeit?

Folgendes Problem: In einer MySQL-Datenbank befinden sich (als Blob), 
mit "ganz gewöhnlichem" ZIP (deflate Modus) erstellte Dateien.

Ich möchte nun die jeweils eine darin enthaltene Text-Datei, wenn 
möglich, mit PHP on-the-fly direkt in einen String-Puffer entpacken, 
ohne vorher nochmal eine Datei zu schreiben. Nach meiner (kurzen) 
Recherche konnter ich aber nur Beispiele mit Dateien finden.

Idee? Tips? Danke.
Gast #6229466
Lesenswert?

zip heisst Du benutzt ein externes tool zum packen und entpacken
(entweder systemtool oder third party)
deflate müsste ja Phil Katz sein, richtig?

egal.. jdf kannst Du per Kommandozeile tricksen und Dir den output je 
nach benutztem tool direkt zurückgeben lassen (exec());
den output kannst Du dann in php in eine Variable schreiben.
Ich halte das aber für ein gewagtes unterfangen;
insbesondere wenn der inhalt nicht bekannt ist (oder dessen grösse)
Du könntest sonst ins memory limit rennen oder schlimmer ungewollt 
malicious code ausführen.

Temp-datei halte ich für sinnvoller wenn Du diese dann sorgsam einliesst 
zur Weiterverabeitung.

'sid
#6232381
Lesenswert?

Ich würde mal das MYSQL Statement "DUMP INTO FILE" anschauen.

Dazu über info.php ob schon ein ZIP-Addon als Standard installiert ist.

Kommt natürlich darauf an wie groß die Zip-Dateien sind welchen Weg man 
einschlagen muss.

Nach unten Scrollen, dort sind die Beispiele.

https://www.php.net/manual/de/ziparchive.open.php

EDIT: Was aber auch gehen könnte, man macht 2 PHP-Scripts.. eines stellt 
nur dem eigenen Host das Zip aus dem Mysql bereit. Falls möglich 
versucht man dann mit Zip-Archiv Open die Url des Scriptes zu öffnen 
vorausgesetzt das URLs als Pfad auch erlaubt sind.
Gast #6233765
Lesenswert?

Ach so.

Anscheinend kann man bei PDO lobs als files öffnen: 
https://www.php.net/manual/en/pdo.lobs.php

Aber ZipArchive nimmt ja leider keinen stream, sondern ein file...

Mein erster Gedanke waren die php:// fake files 
(https://www.php.net/manual/en/wrappers.php.php), insbesondere, aus dem 
stream einen "php://fd/X" Pfad zu konstruieren.
Aber einerseits wüsste ich nicht, wie man an einen file descriptor von 
einem lob stream kommt, und andererseits sind die glaub ich nicht 
seekable, also würde das vermutlich nicht funktionieren.

Dazu, dass die lob non-seekable sind, kommt dann noch dazu, dass der 
index der Zip Dateien am Ende steht, was eine sehr ungünstige 
Kombination ist. Einige Programme können aber anscheinend auch ohne den 
Index mit ner Pipe an die Dateien ran kommen: 
https://stackoverflow.com/questions/7132514/bash-how-to-unzip-a-piped-zip-file-from-wget-qo

Dem stackoverflow thread zufolge können bsdtar und neuere Versionen von 
"busybox unzip" sowas, das normale unzip in debian scheint nicht zu 
gehen, es gäbe auch noch funzip aber das kann nur die erste Datei.

Mit proc_open und stream_get_contents könnte das also sogar gehen: 
https://www.php.net/manual/en/function.proc-open.php

Gelesen würde eventuell aber trotzdem etwas mehr als nötig, wenn auch 
nicht unbedingt die ganze Zip datei.

Wobei, eventuell wäre es doch einfacher, in ein tmpfile zu schreiben, 
und sich den ganzen Aufwand zu sparen, oder das Konzept selbst nochmal 
zu überdenken...
OP (Firma: Q3) #6234681
Lesenswert?

Ich erklär nochmal die Problematik:

1. Ein Zip-Archiv (bzw. viele davon) wurde als Datei-Container erstellt 
und enthält jeweils genau eine TXT-Datei. Das wurde jeweils per FTP auf 
einen Webserver hochgeladen und dort per PHP komplett in einer 
MySQL-Datenbank abgelegt.

2. Dieses ZIP-Archiv (bzw. viele dieser Art) befinden sich nun vom 
ersten bis zum letzten Bit als BLOB in der Mysql-Datenbank

Die Frage ist nun: Gelingt mir der Zugriff auf den Inhalt der Datei in 
dem ZIP-Archiv, nachem ich es mir mit einem SQL-Statement komplett in 
eine String-Variable geladen habe, ohne den Umweg über eine (temporäre) 
Datei? Die ZIP-Archive sind ca. 200 ... 300 kB, ausgepackt max. 1MB.
(Firma: Funkenflug Industries) #6234709
Lesenswert?

Du könntest probieren, das Archiv mit PHP zu parsen, den komprimierten 
Inhalt der Datei in einen String zu laden und diesen dann zu 
dekomprimieren, z.B. mit gzinflate() oder gzuncompress() passend zum 
Archivinhalt.

Das komplette Archiv in einen String wird nicht gehen, da alle diese 
Funktionen darauf aus sind, daß ein Archiv mehrere Dateien enthalten 
kann.
OP (Firma: Q3) #6236126
Lesenswert?

DPA schrieb:
> Frank E. schrieb:
>> nachem ich es mir mit einem SQL-Statement komplett in eine String-Variable
> geladen habe
>
> Warum willst du dass denn tun? Dann müsste ja die ganze ZIP Datei in den
> Speicher? Das macht doch den ganzen Nutzen von (B)LOBs zunichte?

Ich wüsste keinen anderen Weg, an die Daten in einer Datenbank 
heranzukommen, als diese mit einem Select anzufordern. Und dann landen 
die in einer Recordset-Struktur im Speicher, die ich wie eine Variable 
benutzen kann ... Ich lass mir gerne was anderes vorschlagen. An der 
Tatsache, dass die ZIPs in der Datenbak stecken, ist allerdings nicht zu 
rütteln.
Gast #6236236
Lesenswert?

Frank E. schrieb:
> Ich wüsste keinen anderen Weg, an die Daten in einer Datenbank
> heranzukommen, als diese mit einem Select anzufordern. Und dann landen
> die in einer Recordset-Struktur im Speicher, die ich wie eine Variable
> benutzen kann

Sorry, ich habe wohl fälschlicherweise einige nicht zutreffende Annahmen 
gemacht. Ich dachte aufgrund der Dokumentation, das würde gehen, wenn 
man mit PDO darauf zugreift: https://www.php.net/manual/en/pdo.lobs.php

Aber anscheinend gibt es da seit 11 Jahren einen alten Bug: 
https://bugs.php.net/bug.php?id=40913
(Firma: Funkenflug Industries) #6236279
Lesenswert?

Hmmmmm kannst Du mir bitte sagen ob es irgend eine Notwendigkeit gibt, 
komplette ZIP-Archive in der Datenbank zu speichern? Oder könnte man das 
ggf. auch ändern und die Daten "anders komprimiert" in der Datenbank 
ablegen, z.B. als gzdeflate-Ausgabe ohne den ZIP-Container drum herum?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren