web-dev-qa-db-fra.com

PHP Fichiers Zip à la volée

Quelle est la façon la plus simple de compresser, disons 2 fichiers, à partir d'un dossier sur le serveur et de forcer le téléchargement? Sans enregistrer le "Zip" sur le serveur.

    $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.

Quelqu'un peut-il vérifier: J'ai un dossier avec test1.doc, test2.doc et test3.doc

avec l'exemple ci-dessus - fichier1 (fichier2 et fichier3) pourrait simplement être test1.doc, etc.

dois-je faire quoi que ce soit avec "$ filepath1"? Est-ce le répertoire du dossier qui contient les 3 documents?

Désolé pour ma question de base ..

45
Steven

Malheureusement w/PHP 5.3.4-dev et Zend Engine v2.3.0 sur CentOS 5.x, je n'ai pas pu faire fonctionner le code ci-dessus. Un "Zip invalide ou unitaire) object "le message d'erreur était tout ce que je pouvais obtenir. Donc, pour le faire fonctionner, j'ai dû utiliser l'extrait de code suivant (extrait de l'exemple de Jonathan Baltazar sur le manuel PHP.net, sur la page ZipArchive :: open) :

// 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); 

Je sais que c'est différent que de travailler avec de la mémoire uniquement - à moins que vous ayez votre zone tmp dans ram ;-) - mais cela peut peut-être aider quelqu'un d'autre, qui a du mal avec la solution ci-dessus, comme moi; et pour lesquels la pénalité de performance n'est pas un problème.

69
maraspin

Votre code est très proche. Vous devez utiliser le nom de fichier au lieu du contenu du fichier.

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

devrait être

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

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

Si vous devez ajouter des fichiers à partir d'une variable au lieu d'un fichier, vous pouvez utiliser la fonction addFromString.

$Zip->addFromString( 'file1', $data );
9
sakabako

Si vous avez accès à l'utilitaire de ligne de commande Zip, vous pouvez essayer

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

où les fichiers sont les éléments que vous souhaitez compresser et compresser l'emplacement de l'exécutable Zip.

Cela suppose bien sûr Linux ou similaire. Dans Windows, vous pourriez peut-être faire de même avec un autre outil de compression, je suppose.

Il y a aussi extension Zip , utilisation indiquée ici .

5
Vinko Vrsalovic

la réponse de maraspin est ce que j'ai essayé. Étrangement, je l'ai fait fonctionner en supprimant la ligne d'en-tête qui fait référence à la taille du fichier:

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

Avec le changement ci-dessus, le code fonctionne comme une brise! Sans cette modification, j'obtenais le message d'erreur suivant:

Signature de fin de répertoire central introuvable. Soit ce fichier n'est pas un fichier zip, soit il constitue un disque d'une archive en plusieurs parties. Dans ce dernier cas, le répertoire central et le commentaire du fichier zip seront trouvés sur le (s) dernier (s) disque (s) de cette archive.

Environnement de test:

OS: Ubuntu 10.10 Browser: Firefox Et la pile LAMP par défaut.

4
itsols

itsols Si vous souhaitez insérer la 'Content-Length' faites-le comme ceci:

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

Je ne sais pas pourquoi, mais ça plante si vous le mettez dans la même ligne.

1
Arkiller

Pour créer des fichiers Zip à la volée (en mémoire), vous pouvez utiliser la classe ZipFile de phpMyAdmin :

Un exemple de la façon de l'utiliser dans votre propre application:

Remarque: Vos fichiers Zip seront limités par la limite de mémoire de PHP, résultant en des archives corrompues si vous dépassez la limite.

1
dezlov