压缩目录中的所有文件并强制下载

时间:2011-12-05 09:20:37

标签: php zip

我在我的网站上运行以下代码。我遇到的唯一问题是它在服务器上生成一个zip文件然后用户下载。

我想知道我应该做什么才能在运行中“生成”生成zip文件而不先将其转储到服务器磁盘上。我还想让用户暂停/恢复下载。

//function for zip
function zipFilesAndDownload($file_names,$archive_file_name,$file_path)
{
  //create the object
  $zip = new ZipArchive();
  //create the file and throw the error if unsuccessful
  if ($zip->open($archive_file_name, ZIPARCHIVE::CREATE )!==TRUE) {
    exit("cannot open <$archive_file_name>\n");
  }

  //add each files of $file_name array to archive
  foreach($file_names as $files)
  {


  $zip->addFile($file_path.str_replace('./','',$files),translit($files).".mp3");
  }
  $zip->close();

  //then send the headers to foce download the zip file
  header("Content-type: application/zip");
  header("Content-Disposition: attachment; filename=$archive_file_name");
  header("Pragma: no-cache");
  header("Expires: 0");
  readfile("$archive_file_name");
  exit;
}

1 个答案:

答案 0 :(得分:6)

您提到了三个要求:

  • zip is available for download on fly - 我认为,这意味着“zip文件是创建”。这已经发生了。事实上,如果你愿意的话,这就是你的剧本所做的,它是 raison d'etre
  • zip file should not be created on server - 您必须在服务器上创建一个文件,即使它只是暂时的,因为这是Zip扩展的工作方式。您可以在用户下载后将其删除(只需在unlink($archive_file_name);之前的行上添加exit;)。
  • user can also resume it if paused - 此要求(大部分)与zip file should not be created on server不兼容。可恢复的下载 可以在PHP中实现,但是很难做到并且需要访问请求的Range:标头 - 这并不是每个服务器都允许的。此外,您还必须为部分请求生成整个文件,因为您已从服务器中删除它。 Apache具有可恢复下载的实现,但它需要(AFAIK)该文件在硬盘驱动器上是静态的,并且直接请求。这意味着在下载文件后(在PHP脚本的末尾)删除文件会破坏可恢复性。

在这些行之间阅读,我怀疑你遇到的问题是你的服务器的硬盘空间正在被你正在创建的所有Zip档案用尽而不是删除。对此的解决方案(虽然仍然允许可恢复的下载)是在服务器上实现某种形式的TTL检查器,并定期删除比例如1天更早的文件。您可以使用cron作业执行此操作,或者在创建新的arhive时运行检查。

目前,您的代码未指定将创建zip文件的 where ,这是您需要执行的操作。下面是一个示例,假设您的脚本位于站点的根目录中,并且站点的根目录中有一个名为zips的目录。

基本流程是:

     
  • 循环显示 / zips 目录,并删除所有超过1天的文件。  
  • / zips 目录中创建新存档  
  • 将用户重定向到该静态文件的路径。
function zipFilesAndDownload($file_names, $archive_file_name, $file_path) {

  // Archive directory
  $archiveDir = 'zips';
  // Time-to-live
  $archiveTTL = 86400; // 1 day
  // Files to ignore
  $ignoreFiles = array('.', '..');


  // Loop the storage directory and delete old files
  if ($dp = opendir($archiveDir)) {
    while ($file = readdir($dp)) {
      if (!in_array($file, $ignoreFiles) && filectime("$archiveDir/$file") < (time() - $archiveTTL)) {
        unlink("$archiveDir/$file");
      }
    }
  }

  // Re-format the file name
  $archive_file_name = "$archiveDir/".basename($archive_file_name);
  // Create the object
  $zip = new ZipArchive();
  // Create the file and throw the error if unsuccessful
  if ($zip->open($archive_file_name, ZIPARCHIVE::CREATE) !== TRUE) {
    exit("Cannot open '$archive_file_name'\n");
  }
  // Add each file of $file_name array to archive
  foreach($file_names as $file) {
    $zip->addFile($file_path.str_replace('./', '', $file), translit($files).".mp3");
  }
  $zip->close();

  // Then send the headers to redirect to the ZIP file
  header("HTTP/1.1 303 See Other"); // 303 is technically correct for this type of redirect
  header("Location: http://{$_SERVER['HTTP_HOST']}/$archive_file_name");
  exit;

}