【问题标题】:zip and download files using php使用 php 压缩和下载文件
【发布时间】:2013-11-23 12:36:32
【问题描述】:

我正在尝试从名为“upload”的文件夹压缩和下载文件。 Zip 文件正在下载,但我无法打开(提取)它。 我收到类似“存档格式未知或已损坏”之类的错误。

我找到了以下代码来压缩文件夹。

<?php
    $files = "upload/".array('Dear GP.docx','ecommerce.doc');
    $zipname = 'filename.zip';
    $zip = new ZipArchive;
    $zip->open($zipname, ZipArchive::CREATE);
    foreach ($files as $file) {
      $zip->addFile($file);
    }
    $zip->close();
    header('Content-Type: application/zip');
    header('Content-disposition: attachment; filename=filename.zip');
    header('Content-Length: ' . filesize($zipfilename));
    readfile($zipname);
?>

【问题讨论】:

  • 该问题可能与$files = "upload/".array('Dear GP.docx','ecommerce.doc'); 有关。尝试显示错误并检查 PHP 错误。您正在尝试将数组转换为字符串。

标签: php zip


【解决方案1】:

感谢您的回答。

<?php
    $files = array('Dear GP.docx','ecommerce.doc');

    # create new zip opbject
    $zip = new ZipArchive();

    # create a temp file & open it
    $tmp_file = tempnam('.','');
    $zip->open($tmp_file, ZipArchive::CREATE);

    # loop through each file
    foreach($files as $file){

        # download file
        $download_file = file_get_contents($file);

        #add it to the zip
        $zip->addFromString(basename($file),$download_file);

    }

    # close zip
    $zip->close();

    # send the file to the browser as a download
    header('Content-disposition: attachment; filename=Resumes.zip');
    header('Content-type: application/zip');
    readfile($tmp_file);
 ?>

【讨论】:

  • 编辑掉这个答案中提出新问题的部分。 Please use Answers exclusively to answer the question。如果您有新问题,请点击 按钮提出问题。如果有助于提供上下文,请包含指向此问题的链接。
  • 我相信大多数人都不希望临时文件在之后保留,所以要删除该文件,只需在readfile($tmp_file); 之后执行unlink($tmp_file);,只是一个快速提醒
  • 这很棒,因为它去掉了文件夹结构
【解决方案2】:

我花了 6 个多小时在我的 mac (localhost) 上下载 zip 文件 - 虽然文件正在下载,但我无法解压缩它们(获取 cpgz 文件)。显然,堆栈溢出中提到的解决方案(围绕 zip 文件下载的各种问题)都不起作用。最后,经过反复试验,我发现以下代码有效:

之前回答的人都没有谈到 ob_start() 以及你应该把它放在哪里。无论如何,仅此一项不是答案 - 您还需要使用 ob_start() 上方的那三行代码。

$file=$zippath.$filename;
if (headers_sent()) {
    echo 'HTTP header already sent';
} else {
    if (!is_file($file)) {
        header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
        echo 'File not found';
    } else if (!is_readable($file)) {
        header($_SERVER['SERVER_PROTOCOL'].' 403 Forbidden');
        echo 'File not readable';
    } else {
        while (ob_get_level()) {
            ob_end_clean();
        }
       ob_start();
       header($_SERVER['SERVER_PROTOCOL'].' 200 OK');
       header("Content-Type: application/zip");
       header("Content-Transfer-Encoding: Binary");
       header("Content-Length: ".filesize($file));
       header('Pragma: no-cache');
       header("Content-Disposition: attachment; filename=\"".basename($file)."\"");
       ob_flush();
       ob_clean();
       readfile($file);
       exit;
   }
}

【讨论】:

  • 据我所知(当然可能是错误的)ob_end_clean() 行与缓存有关,因为大文件会被缓存弄乱。
【解决方案3】:

请使用以下代码代替 $zip->addFile($file);

<?php
$zip->addFile($file_path, $filename);
?>

【讨论】:

  • 这不是问题。 $filenameoptional 参数
  • 好的。我正在使用文件名创建 zip 文件,所以我建议使用文件路径和文件名这两个选项。
【解决方案4】:
$files = "upload/".array('Dear GP.docx','ecommerce.doc');

应该是:

$files = array('upload/Dear GP.docx','upload/ecommerce.doc');

如果您仍然遇到问题,那么您应该检查您是否具有对当前目录的写入权限。可以查看close()的返回值来判断文件是否真的被写入了。

$res = $zip->close();
var_dump($res);

如果写入成功,输出应该是bool(true)

看起来您在 filesize() 调用中也有错误的 var 名称:

header('Content-Length: ' . filesize($zipfilename));

应该是:

header('Content-Length: ' . filesize($zipname));

您还可以添加额外的验证来检查您添加到 zip 中的文件是否确实存在,并在发送之前检查 zip 文件是否存在。

编辑:开启显示错误以帮助您在本地调试:

ini_set('display_errors', 1);
error_reporting(E_ALL);

【讨论】:

    【解决方案5】:

    答案很好,但请在标题前添加这些行。 Zip 文件在所有 zip 软件(winzip、winrar 等)中都打开

    if (headers_sent()) 
        {
            // HTTP header has already been sent
            return false;
        }
    // clean buffer(s)
    while (ob_get_level() > 0)
        {
            ob_end_clean();
        }
    

    【讨论】:

      【解决方案6】:
       $zip = new ZipArchive;
              if ($zip->open('assets/myzip.zip',  ZipArchive::CREATE)) {
                  $zip->addFile('folder/bootstrap.js', 'bootstrap.js');
                  $zip->addFile('folder/bootstrap.min.js', 'bootstrap.min.js');
                  $zip->close();
                  echo 'Archive created!';
                  header('Content-disposition: attachment; filename=files.zip');
                  header('Content-type: application/zip');
                  readfile($tmp_file);
             } else {
                 echo 'Failed!';
             }
      

      我得到了从文件夹下载文件的代码。

      【讨论】:

        【解决方案7】:

        我有一个客户端“全部下载”按钮,用于存储在网络服务器上的并行目录中的文件。与 OP 存在类似问题,以下代码是在阅读了许多类似的帖子后创建的。

        服务器在 Ubuntu 20 上运行 php7.4,别忘了安装你的 php 版本的 zip,我的是 php7.4-zip。 HTML 使用 Bootstrap 4.5.2 和 font-awesome 5.13.0

        <?php
        if( isset( $_POST["downloadAll"] ) ){
        
            // all folders in remote dir are given a UID as a name
            $directory = "../remoteLinuxDirectory/" . $_SESSION["folderID"];
            $fileNames = scandir( $directory );
            
            // create new archive 
            $zip = new ZipArchive;
        
            // create a temporary file for zip creation
            $tmp_file = tempnam( $directory, $_SESSION["folderName"] );
        
            if( $zip->open( $tmp_file, ZipArchive::CREATE ) ){ 
        
                // $i = 0,1 show the dot and double dot directory in linux
                $i=2; 
        
                while( $i < count( $fileNames ) ){ 
        
                   // addFile( 'from location', 'name of individual file')
                   $zip->addFile( $directory . "/" . $fileNames[ $i ], $fileNames[ $i ] ); 
                   $i++;
                }
        
                $zip->close();
            
                // remove special characters from the about-to-be-created zip filename 
                $cleanName = str_replace(array( ".",",","/","\\"," "),'', $_SESSION["folderName"])
                header("Content-disposition: attachment; filename=" . $cleanName . ".zip");
                header('Content-type: application/zip');
        
                // begin the zip download
                readfile( $tmp_file );
        
                // removes the temporary file created in the "../remoteLinuxDirectory/"
                unlink( $tmp_file );
        
            }else{
                // can be removed, but will dump some info incase the $zip->open fails
                var_dump( $tmp_file );
            }
        }
        ?>
        

        一个 HTML 按钮:

        <form action="" method="post">
            <button class="btn btn-primary p-2 px-3">
                <input  name="downloadAll" value="1" hidden>
                <i class="fas fa-download"></i> Download All
            </button>
        </form>
        

        【讨论】:

          猜你喜欢
          • 2014-12-01
          • 2011-05-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多