Как создать ZIP-файл с помощью PHP и удалить его после загрузки пользователем? - PullRequest
18 голосов
/ 09 апреля 2011

Мне нужно загрузить изображения с других сайтов на мой сервер.Создайте ZIP-файл с этими изображениями.автоматически начать загрузку созданного файла ZIP.После завершения загрузки ZIP-файл и изображения должны быть удалены с моего сервера.

Вместо автоматической загрузки, ссылка на скачивание тоже подойдет.но другая логика остается той же.

Ответы [ 8 ]

21 голосов
/ 09 апреля 2011

Хорошо, вам сначала нужно создать zip-файл, используя класс ZipArchive.

Затем отправьте:

  • Правильные заголовки, указывающие браузеру, что он должен загрузить что-то в виде почтового индекса - см. header() - на странице этого руководства есть пример, который должен помочь
  • содержимое zip-файла, используя readfile()

И, наконец, удалите zip-файл с вашего сервера, используя unlink().


Примечание: в качестве меры безопасности может быть целесообразно, чтобы PHP-скрипт выполнялся автоматически (обычно crontab) ,это приведет к удалению старых zip-файлов во временном каталоге.

Это на тот случай, если ваш обычный PHP-скрипт иногда прерывается и не удаляет временный файл.

14 голосов
/ 28 мая 2012
<?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();
}

?>
3 голосов
/ 09 апреля 2011

Есть идеи, сколько загрузок zip-файлов прервано и их необходимо продолжить?

Если продолжительные загрузки составляют небольшой процент ваших загрузок, вы можете немедленно удалить файл zip; пока ваш сервер все еще отправляет файл клиенту, он останется на диске.

Как только сервер закроет дескриптор файла, счетчик ссылок на файл упадет до нуля и, наконец, его блоки на диске будут освобождены.

Но вы могли бы потратить немало времени на воссоздание zip-файлов, если многие загрузки прерываются. Хорошая дешевая оптимизация , если , то с этим можно сойти.

2 голосов
/ 16 ноября 2017

Другое решение: Удалите прошлые файлы перед созданием нового 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
    }
2 голосов
/ 09 апреля 2011

Вот как я смог сделать это в прошлом.Этот код предполагает, что вы записали файлы по пути, указанному в переменной $path.Возможно, вам придется решить некоторые проблемы с разрешениями в конфигурации вашего сервера, используя 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);
1 голос
/ 01 июля 2013

Включить расширение php_curl;(php.ini), затем используйте приведенный ниже код для создания почтового индекса.создайте класс папки и используйте код, указанный ниже:

<?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;

    ?>

создайте класс папки и используйте код, указанный ниже:

<?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; 
            }



    }

    ?>
0 голосов
/ 12 ноября 2018

Я отправился туда в поисках аналогичного решения, и после прочтения комментариев обнаружил этот оборот: перед созданием вашего zip-файла в отдельной папке (здесь она называется «zip_files», удалите все zip, которые, по вашему мнению, старше разумного времени (Потребовалось 24 часа):

$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

Таким образом, после 24 часов вы создаете только последние архивы, пользователь за пользователем. Ничто не мешает вам иногда выполнять задачу clean by cron, но проблема с задачей cronесли кто-то использует zip-архив при запуске cron, это приведет к ошибке. Здесь единственно возможная ошибка - если кто-то ждет 24 часа, чтобы выполнить DL архив.

0 голосов
/ 09 апреля 2011

Во-первых, вы загружаете изображения с веб-сайта

затем, с файлами, которые вы скачали, вы создаете zipfile (отличный вариант)

наконец, вы отправили этот zip-файл в браузер, используя readfile и заголовки (см. Пример 1)

...