如何使用 PHP 创建 ZIP 文件并在用户下载后将其删除?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5603851/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 21:57:17  来源:igfitidea点击:

How to create a ZIP file using PHP and delete it after user downloads it?

phpdownloadzip

提问by Joby Joseph

I need to download images from other websites to my server. Create a ZIP file with those images. automatically start download of created ZIP file. once download is complete the ZIP file and images should be deleted from my server.

我需要从其他网站下载图像到我的服务器。使用这些图像创建一个 ZIP 文件。自动开始下载创建的 ZIP 文件。下载完成后,应从我的服务器中删除 ZIP 文件和图像。

Instead of automatic download, a download link is also fine. but other logic remains same.

除了自动下载,下载链接也很好。但其他逻辑保持不变。

回答by Pascal MARTIN

Well, you'll have to first create the zipfile, using the ZipArchiveclass.

好吧,您必须首先使用ZipArchive该类创建 zipfile 。

Then, send :

然后,发送:

  • The right headers, indicating to the browser it should download something as a zip -- see header()-- there is an example on that manual's page that should help
  • The content of the zip file, using readfile()
  • 正确的标题,向浏览器指示它应该以 zip 格式下载某些内容——请参阅header()——该手册页面上有一个示例,应该会有所帮助
  • zip 文件的内容,使用 readfile()

And, finally, delete the zip file from your server, using unlink().

最后,使用 .zip 文件从您的服务器中删除 zip 文件unlink()


Note : as a security precaution, it might be wise to have a PHP script running automatically (by crontab, typically), that would delete the old zip files in your temporary directory.


注意:作为安全预防措施,让 PHP 脚本自动运行(通常通过 crontab)可能是明智的,这会删除临时目录中的旧 zip 文件。

This just in case your normal PHP script is, sometimes, interrupted, and doesn't delete the temporary file.

这只是为了防止您的正常 PHP 脚本有时被中断,并且不会删除临时文件。

回答by Mahesh Ambig

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

?>

回答by sarnold

Any idea how many zip file downloads get interrupted and need to be continued?

知道有多少 zip 文件下载被中断并需要继续吗?

If continued downloads are a small percentage of your downloads, you can delete the zip file immediately; as long as your server is still sending the file to the client, it'll remain on disk.

如果继续下载只占您下载的一小部分,您可以立即删除 zip 文件;只要您的服务器仍在向客户端发送文件,它就会保留在磁盘上。

Once the server closes the file descriptor, the file's reference count will drop to zero, and finally its blocks on disk will be released.

一旦服务器关闭文件描述符,文件的引用计数将降为零,最后它在磁盘上的块将被释放。

But, you might spent a fair amount of time re-creating zip files if many downloads get interrupted though. Nice cheap optimization ifyou can get away with it.

但是,如果许多下载中断,您可能会花费大量时间重新创建 zip 文件。如果你能侥幸逃脱,那是不错的廉价优化。

回答by Eric Conner

Here's how I've been able to do it in the past. This code assumes you've written the files to a path specified by the $pathvariable. You might have to deal with some permissions issues on your server configuration with using php's exec

这就是我过去能够做到的方式。此代码假定您已将文件写入由$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);

回答by Intacto

Other solution: Delete past files before creation new zip file:

其他解决方案:在创建新的 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
    }

回答by Romain Bel

I went there looking for a similar solution, and after reading the comments found this turnover : before creating your zip file in a dedicated folder (here called 'zip_files', delete all zip you estimate being older than a reasonable time (I took 24h) :

我去那里寻找类似的解决方案,并在阅读评论后发现此营业额:在专用文件夹中创建您的 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

By doing so, after 24h you only have the last zips created, user by user. Nothing prevents you for doing a clean by cron task sometimes, but the problem with the cron task is if someone is using the zip archive when the cron is executed it will lead to an error. Here the only possible error is if someone waits 24h to DL the archive.

通过这样做,24 小时后,您只能按用户创建最后一个 zip。有时没有什么可以阻止您通过 cron 任务进行清理,但是 cron 任务的问题是,如果有人在执行 cron 时使用了 zip 存档,则会导致错误。这里唯一可能的错误是如果有人等待 24 小时来 DL 存档。

回答by Vineesh Kalarickal

Enable your php_curl extension; (php.ini),Then use the below code to create the zip. create a folder class and use the code given below:

启用你的 php_curl 扩展;(php.ini),然后使用下面的代码创建zip。创建一个文件夹类并使用下面给出的代码:

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

    ?>

create a folder class and use the code given below:

创建一个文件夹类并使用下面给出的代码:

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



    }

    ?>

回答by Elijan Sejic

Firstly, you download images from webiste

首先,您从网站下载图像

then, with the files you have downloaded you creatae zipfile(great tute)

然后,使用您下载的文件创建zipfile(很棒)

finally you sent this zip file to browser using readfile and headers(see Example 1)

最后,您使用readfile 和 headers将此 zip 文件发送到浏览器(参见示例 1)