2009-06-30 7 views
40

Was ist der einfachste Weg, zip, sagen 2 Dateien, aus einem Ordner auf dem Server und erzwingen Download? Ohne die "Zip" auf dem Server zu speichern.PHP ZIP-Dateien im laufenden Betrieb

$zip = new ZipArchive(); 
    //the string "file1" is the name we're assigning the file in the archive 
$zip->addFile(file_get_contents($filepath1), 'file1'); //file 1 that you want compressed 
$zip->addFile(file_get_contents($filepath2), 'file2'); //file 2 that you want compressed 
$zip->addFile(file_get_contents($filepath3), 'file3'); //file 3 that you want compressed 
echo $zip->file(); //this sends the compressed archive to the output buffer instead of writing it to a file. 

Kann jemand überprüfen: Ich habe einen Ordner mit Test1.doc, Test2.doc und test3.doc

mit dem obigen Beispiel - file1 (file2 und file3) könnte nur Test1.doc sein usw.

muss ich irgendetwas mit "$ filepath1" machen? Ist das das Ordnerverzeichnis, das die 3 Dokumente enthält?

Sorry für meine grundlegende Frage ..

+0

Laut der [Dokumentation] (http://us3.php.net/manual/en/class.ziparchive.php) hat die ZipArchive-Klasse keine function file() und dies wird zu einem Fehler führen. Um dies zu tun braucht eine andere Bibliothek wie zum Beispiel [diese] (http://stackoverflow.com/questions/1189019/manipulate-an-archive-in-memory-with-php-without-creating-a- temporäre Datei-auf-d). Stellen Sie es einfach so hin, dass andere Leute nicht stundenlang versuchen werden, dies mit den unten stehenden Vorschlägen zum Laufen zu bringen. – Neograph734

Antwort

4

Wenn Sie Zugriff auf das Dienstprogramm zip Kommandozeile haben, können Sie

<?php 
$zipped_data = `zip -q - files`; 
header('Content-type: application/zip'); 
header('Content-Disposition: attachment; filename="download.zip"'); 
echo $zipped_data; 
?> 

wo Dateien versuchen, die Dinge, die Sie packen möchten, und Reißverschluss über die Lage auf dem Reißverschluss ausführbar.

Dies setzt natürlich Linux oder ähnliches voraus. In Windows könnte man ähnlich mit einem anderen Komprimierungsprogramm arbeiten, denke ich.

Es gibt auch eine zip extension, Verwendung gezeigt here.

+0

Bearbeiten Sie Ihre Frage mit dem Fehler, den Sie erhalten. Der erste Verdacht ist, dass Sie die Zip-Erweiterung nicht installiert haben. –

9

Ihr Code ist sehr nah. Sie müssen den Dateinamen anstelle des Dateiinhalts verwenden.

$zip->addFile(file_get_contents($filepath1), 'file1'); 

sollte

$zip->addFile($filepath1, 'file1'); 

http://us3.php.net/manual/en/function.ziparchive-addfile.php

sein Wenn Sie Dateien von einer Variablen hinzufügen müssen statt einer Datei, die Sie die AddFromString Funktion verwenden können.

$zip->addFromString('file1', $data); 
+0

Ich stimme dem zu, aber Sie müssen etwas wie Vinko verwenden, um einen Header zu erzwingen, um den Browser zum Download zu bekommen. – m4rc

61

Leider w/PHP 5.3.4-dev und Zend Engine v2.3.0 auf CentOS 5.x ich nicht den Code oben arbeiten konnte. Eine "Ungültige oder unitalisierte Zip-Objekt" Fehlermeldung war alles, was ich bekommen konnte. Also, um es funktioniert, hatte ich folgende Schnipsel zu verwenden (aus dem Beispiel von Jonathan Baltazar auf PHP.net Handbuch, am ZipArchive :: open Seite):

// Prepare File 
$file = tempnam("tmp", "zip"); 
$zip = new ZipArchive(); 
$zip->open($file, ZipArchive::OVERWRITE); 

// Stuff with content 
$zip->addFromString('file_name_within_archive.ext', $your_string_data); 
$zip->addFile('file_on_server.ext', 'second_file_name_within_archive.ext'); 

// Close and send to users 
$zip->close(); 
header('Content-Type: application/zip'); 
header('Content-Length: ' . filesize($file)); 
header('Content-Disposition: attachment; filename="file.zip"'); 
readfile($file); 
unlink($file); 

Ich weiß, das ist anders als nur mit Speicher zu arbeiten - es sei denn, du hast deinen tmp-Bereich im RAM ;-) - aber vielleicht kann das jemand anderem helfen, der mit der obigen Lösung zu kämpfen hat, wie ich es war; und für die Leistung Strafe ist kein Problem.

+0

das hat mir heute geholfen, danke. Wenn es um ein admin/cms-System geht, das PDFs im laufenden Betrieb erzeugt, ist die Leistung sekundär, alle diese Dateien zusammenzufassen, so dass ich den Administrator nicht mit 15 Downloaddialogen überschwemmen muss :) – jammypeach

+0

Weiß jemand, ob es irgendwelche Probleme geben kann mit dem Löschen der Datei direkt nachdem wir es im Ausgabepuffer gelesen haben? Oder ist dieser Ansatz kugelsicher? –

3

Maraspin's Antwort ist was ich ausprobiert habe. Merkwürdigerweise habe ich es durch die Arbeit der Kopfzeile zu entfernen, die die Dateigröße verweist:

header('Content-Length: ' . filesize($file)); 

Mit der obigen Änderung, funktioniert der Code wie ein Kinderspiel! Ohne diese Änderung habe ich die folgende Fehlermeldung angezeigt:

End-of-Central-Verzeichnis-Signatur nicht gefunden. Entweder ist diese Datei keine ZIP-Datei oder sie stellt eine Festplatte eines mehrteiligen Archivs dar.Im letzteren Fall wird der Kommentar des zentralen Verzeichnisses und der ZIP-Datei auf der/den letzten Diskette (n) dieses Archivs gefunden.

Testumgebung:

OS: Ubuntu 10.10 Browser: Firefox Und der Standard-LAMP-Stack.

+0

Halleluja !!!!! – Stevo

+0

Die Kopfzeile ist "Content-Length" und die Dateigröße, nicht die Länge, wurde darauf eingestellt. Das ist vielleicht warum? – Parziphal

1

itsols Wenn Sie den ‚Content-Length‘ eingefügt werden soll tun es wie folgt aus:

$length = filesize($file); 
header('Content-Length: ' . $length); 

Ich weiß nicht, warum, aber es stürzt ab, wenn Sie es in der gleichen Zeile.