web-dev-qa-db-fra.com

Comment créer un fichier Zip en utilisant PHP et le supprimer après que l'utilisateur l'ait téléchargé?

J'ai besoin de télécharger des images d'autres sites sur mon serveur. Créez un fichier Zip avec ces images. démarrer automatiquement le téléchargement du fichier Zip créé. une fois le téléchargement terminé, le fichier Zip et les images doivent être supprimés de mon serveur.

Au lieu du téléchargement automatique, un lien de téléchargement convient également. mais une autre logique reste la même.

15
Joby Joseph

Eh bien, vous devrez d’abord créer le fichier zip, en utilisant la classe ZipArchive .

Ensuite, envoyez:

  • Les en-têtes de droite, indiquant au navigateur qu'il doit télécharger quelque chose au format Zip - voirheader()- un exemple sur la page de ce manuel devrait vous aider.
  • Le contenu du fichier Zip, en utilisant readfile()

Et enfin, supprimez le fichier Zip de votre serveur en utilisant unlink() .


Remarque: par mesure de sécurité, il peut être judicieux d’avoir un script PHP exécuté automatiquement (par crontab, généralement)}, qui supprime les anciens fichiers Zip dans votre répertoire temporaire.

Ceci au cas où votre script PHP normal est parfois interrompu et ne supprime pas le fichier temporaire.

19
Pascal MARTIN
<?php 

Zip('some_directory/','test.Zip');

if(file_exists('test.Zip')){
    //Set Headers:
    header('Pragma: public');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime('test.Zip')) . ' GMT');
    header('Content-Type: application/force-download');
    header('Content-Disposition: inline; filename="test.Zip"');
    header('Content-Transfer-Encoding: binary');
    header('Content-Length: ' . filesize('test.Zip'));
    header('Connection: close');
    readfile('test.Zip');
    exit();
}

if(file_exists('test.Zip')){
    unlink('test.Zip');

}


function Zip($source, $destination)
{
    if (!extension_loaded('Zip') || !file_exists($source)) {
        return false;
    }

    $Zip = new ZipArchive();
    if (!$Zip->open($destination, ZIPARCHIVE::CREATE)) {
        return false;
    }

    $source = str_replace('\\', '/', realpath($source));

    if (is_dir($source) === true)
    {
        $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);

        foreach ($files as $file)
        {
            $file = str_replace('\\', '/', realpath($file));

            if (is_dir($file) === true)
            {
                $Zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
            }
            else if (is_file($file) === true)
            {
                $Zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
            }
        }
    }
    else if (is_file($source) === true)
    {
        $Zip->addFromString(basename($source), file_get_contents($source));
    }

    return $Zip->close();
}

?>
13
Mahesh Ambig

Avez-vous une idée du nombre de téléchargements de fichiers Zip interrompus et devant être poursuivis?

Si les téléchargements continus ne représentent qu'un faible pourcentage de vos téléchargements, vous pouvez supprimer le fichier Zip immédiatement; tant que votre serveur envoie toujours le fichier au client, il reste sur le disque.

Une fois que le serveur a fermé le descripteur de fichier, le nombre de références du fichier passe à zéro et ses blocs sur le disque sont libérés.

Cependant, vous pouvez passer assez de temps à recréer des fichiers Zip si de nombreux téléchargements sont interrompus. Belle optimisation pas cher si vous pouvez vous en tirer.

3
sarnold

Voici comment j'ai été capable de le faire dans le passé. Ce code suppose que vous avez écrit les fichiers dans un chemin spécifié par la variable $path. Vous pourriez avoir à traiter certains problèmes d'autorisations sur la configuration de votre serveur avec l'utilisation de php exec

 // write the files you want to Zip up
file_put_contents($path . "/file", $output);

// Zip up the contents
chdir($path);
exec("Zip -r {$name} ./");

$filename = "{$name}.Zip";

header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.urlencode($filename));
header('Content-Transfer-Encoding: binary');

readfile($filename);
2
Eric Conner

Activez votre extension php_curl; (php.ini), utilisez ensuite le code ci-dessous pour créer le Zip. , créez une classe de dossiers et utilisez le code donné ci-dessous:

<?php 
    include("class/create_Zip.php");
    $create_Zip     =   new create_Zip();
    //$url_path,$url_path2 you can use your directory path
            $urls = array(
                 '$url_path/file1.pdf',         
                 '$url_path2/files/files2.pdf'
                 ); // file paths 


            $file_name      =   "vin.Zip";   // Zip file default name
            $file_folder    =   Rand(1,1000000000); // folder with random name
            $create_Zip->create_Zip($urls,$file_folder,$file_name);  
            $create_Zip->delete_directory($file_folder);  //delete random folder 

            if(file_exists($file_name)){
             $temp = file_get_contents($file_name);     
             unlink($file_name); 
            }       

            echo $temp;

    ?>

créez une classe de dossiers et utilisez le code ci-dessous:

<?php

    class create_Zip{

        function create_Zip($urls,$file_folder,$file_name){

            header('Content-Type: application/octet-stream'); 
            header('Content-Disposition: attachment; filename='.$file_name); 
            header('Content-Transfer-Encoding: binary');

                $mkdir  =   mkdir($file_folder); 

                $Zip    = new ZipArchive;
                $Zip->open($file_name, ZipArchive::CREATE); 

                foreach ($urls as $url)
                {
                     $path=pathinfo($url);     
                     $path = $file_folder.'/'.$path['basename'];
                     $Zip->addFile($path);     
                     $fileopen = fopen($path, 'w');     
                     $init = curl_init($url);     
                     curl_setopt($init, CURLOPT_FILE, $fileopen);     
                     $data = curl_exec($init);     
                     curl_close($init);     
                     fclose($fileopen); 
                } 

                $Zip->close();


            }

            function delete_directory($dirname) 
            {
                if (is_dir($dirname))
                $dir_handle = opendir($dirname); 
                if (!$dir_handle)
                return false;
                    while($file = readdir($dir_handle))
                    {
                        if ($file != "." && $file != "..") 
                        {
                            if (!is_dir($dirname."/".$file))             
                            unlink($dirname."/".$file);          
                            else            
                            delete_directory($dirname.'/'.$file);           
                        }    
                    }
                closedir($dir_handle);    
                rmdir($dirname);    
                return true; 
            }



    }

    ?>
1
Vineesh Kalarickal

Autre solution: Supprimez les anciens fichiers avant de créer un nouveau fichier Zip:

    // Delete past Zip files script
    $files = glob('*.Zip'); //get all file names in array
    $currentTime = time(); // get current time
    foreach($files as $file){ // get file from array
        $lastModifiedTime = filemtime($file); // get file creation time

        // get how old is file in hours:
        $timeDiff = abs($currentTime - $lastModifiedTime)/(60*60);

        //check if file was modified before 1 hour:
        if(is_file($file) && $timeDiff > 1)
            unlink($file); //delete file
    }
1
Intacto

J'y suis allé à la recherche d'une solution similaire, et après avoir lu les commentaires, j'ai constaté ce chiffre d'affaires: avant de créer votre fichier Zip dans un dossier dédié (ici appelé 'Zip_files', supprimez tous les fichiers Zip que vous estimez être plus anciens qu'un temps raisonnable (j'ai pris 24h) :

$dossier_Zip='Zip_files';   
    if(is_dir($dossier_Zip))
        {
        $t_Zip=$dossier_Zip.'/*.Zip'; #this allow you to let index.php, .htaccess and other stuffs...
        foreach(glob($t_Zip) as $old_Zip)
            {
            if(is_file($old_Zip) and filemtime($old_Zip)<time()-86400)
                {
                unlink($old_Zip);
                }
            }

        $zipname=$dossier_Zip.'/whatever_you_want_but_dedicated_to_your_user.Zip';
        if(is_file($zipname))
            {
            unlink($zipname); #to avoid mixing 2 archives
            }

        $Zip=new ZipArchive;
#then do your Zip job

Ainsi, au bout de 24h, vous n’avez plus que les derniers zips créés, utilisateur par utilisateur. Rien ne vous empêche parfois de faire une tâche cron, mais le problème de la tâche cron est que si quelqu'un utilise l'archive Zip lors de l'exécution du cron, une erreur se produit. Ici, la seule erreur possible est si quelqu'un attend 24h pour DL l'archive.

0
Romain Bel