【问题标题】:How to create a ZIP file using PHP and delete it after user downloads it?如何使用 PHP 创建 ZIP 文件并在用户下载后将其删除?
【发布时间】:2011-04-09 08:36:42
【问题描述】:

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

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

【问题讨论】:

  • 到目前为止您尝试过什么? Stack Overflow 不在这里为您提供源代码。你需要自己尝试解决这个问题。如果您遇到特定问题/问题,请先检查其他用户是否尚未提出相同问题,然后再发布有针对性的问题。

标签: php download zip


【解决方案1】:

好吧,您必须首先使用 ZipArchive 类创建 zip 文件。

然后,发送:

  • 正确的标题,向浏览器表明它应该以 zip 的形式下载一些东西——请参阅 header()——该手册页面上有一个示例应该会有所帮助
  • 压缩文件的内容,使用readfile()

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


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

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

【讨论】:

  • 我猜当用户暂停下载时它会崩溃,但除此之外我认为这是最好的解决方案
【解决方案2】:
<?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();
}

?>

【讨论】:

  • zip 文件永远不会被删除。
  • 实际上不可能从这段代码中删除 zip 文件,因为您不知道下载何时完成。确实你需要通过 cron 作业删除文件。
  • 不能把zip文件读成字符串,然后删除文件吗?当然,仅适用于相对较小的文件,但仍然是一种不错的方法。
【解决方案3】:

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

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

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

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

【讨论】:

  • 谢谢,这是很好的信息,确实是解决问题所需的唯一信息。不知道为什么不多投赞成票。
【解决方案4】:

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

【讨论】:

    【解决方案5】:

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

    【讨论】:

    • 好吧,如果我自己现在正在下载一个文件,然后创建另一个下载,这会删除我已经加载的文件怎么办?还是我在这里遗漏了什么?
    【解决方案6】:

    启用您的 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;
    
        ?>
    

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

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

    【讨论】:

      【解决方案7】:

      我去那里寻找类似的解决方案,并在阅读 cmets 后发现此营业额:在专用文件夹(此处称为“zip_files”)中创建您的 zip 文件之前,删除您估计超过合理时间的所有 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 小时后,您只需要逐个用户创建最后一个 zip。有时没有什么可以阻止您通过 cron 任务进行清理,但 cron 任务的问题是,如果有人在执行 cron 时使用 zip 存档,则会导致错误。这里唯一可能的错误是如果有人等待 24 小时来 DL 存档。

      【讨论】:

        【解决方案8】:

        首先,你从网站下载图片

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-14
          • 2017-10-20
          • 1970-01-01
          相关资源
          最近更新 更多