【问题标题】:How do you create a .gz file using PHP?如何使用 PHP 创建 .gz 文件?
【发布时间】:2011-08-29 17:25:33
【问题描述】:

我想在我的服务器上使用 PHP 对文件进行 gzip 压缩。有没有人有输入文件输出压缩文件的例子?

【问题讨论】:

    标签: php compression gzip


    【解决方案1】:

    这段代码可以解决问题

    // Name of the file we're compressing
    $file = "test.txt";
    
    // Name of the gz file we're creating
    $gzfile = "test.gz";
    
    // Open the gz file (w9 is the highest compression)
    $fp = gzopen ($gzfile, 'w9');
    
    // Compress the file
    gzwrite ($fp, file_get_contents($file));
    
    // Close the gz file and we're done
    gzclose($fp);
    

    【讨论】:

    • 不幸的是,这可能会将整个文件读入内存,可能会达到 PHP 对大文件的内存限制。 :-(
    • 而 w9 是最高压缩率?这是最低压缩率,仅用于在 .gz 中打包数据?
    • @SimonEast 切中要害。这个函数会达到你对大文件的内存限制(你知道吗?gzip 用于压缩那种大文件)。好的答案是上面那个不是这个
    【解决方案2】:

    另外,您可以使用 php 的 wrapperscompression ones。只需对代码稍作改动,您就可以在 gzip、bzip2 或 zip 之间切换。

    $input = "test.txt";
    $output = $input.".gz";
    
    file_put_contents("compress.zlib://$output", file_get_contents($input));
    

    compress.zlib:// 更改为 compress.zip:// 以进行 zip 压缩 (请参阅此答案关于 zip 压缩的评论),或将 compress.bzip2:// 更改为 bzip2 压缩。 p>

    【讨论】:

    【解决方案3】:

    此处的其他答案在压缩期间将整个文件加载到内存中,这将导致大文件出现“内存不足”错误。下面的函数对大文件应该更可靠,因为它以 512kb 的块读取和写入文件。

    /**
     * GZIPs a file on disk (appending .gz to the name)
     *
     * From http://stackoverflow.com/questions/6073397/how-do-you-create-a-gz-file-using-php
     * Based on function by Kioob at:
     * http://www.php.net/manual/en/function.gzwrite.php#34955
     * 
     * @param string $source Path to file that should be compressed
     * @param integer $level GZIP compression level (default: 9)
     * @return string New filename (with .gz appended) if success, or false if operation fails
     */
    function gzCompressFile($source, $level = 9){ 
        $dest = $source . '.gz'; 
        $mode = 'wb' . $level; 
        $error = false; 
        if ($fp_out = gzopen($dest, $mode)) { 
            if ($fp_in = fopen($source,'rb')) { 
                while (!feof($fp_in)) 
                    gzwrite($fp_out, fread($fp_in, 1024 * 512)); 
                fclose($fp_in); 
            } else {
                $error = true; 
            }
            gzclose($fp_out); 
        } else {
            $error = true; 
        }
        if ($error)
            return false; 
        else
            return $dest; 
    } 
    

    【讨论】:

    • 完美!正是我需要的。
    • 非常好的代码。我采用了上述方法并创建了反向来解压缩文件。代码相当快。
    【解决方案4】:

    gzencode() 简单的一个班轮:

    gzencode(file_get_contents($file_name));
    

    【讨论】:

    【解决方案5】:

    如果您只想解压缩文件,这可以正常工作并且不会导致内存问题:

    $bytes = file_put_contents($destination, gzopen($gzip_path, r));
    

    【讨论】:

      【解决方案6】:

      这对很多人来说可能很明显,但是如果您的系统上启用了任何程序执行功能(execsystemshell_exec),您可以使用它们来简单地gzip 文件。

      exec("gzip ".$filename);
      

      注意:请务必在使用 $filename 变量之前对其进行正确清理,尤其是当它来自用户输入时(但不仅如此)。它可用于运行任意命令,例如包含my-file.txt && anothercommand(或my-file.txt; anothercommand)之类的内容。

      【讨论】:

      • exec 在大多数托管平台上被锁定,一般来说甚至使用 exec 都会带来安全风险
      • @Wranorn 这就是为什么我指出“如果您的系统上启用了任何程序执行功能”,我应该写“在您的托管平台上”吗?至于安全性,如果您不将用户输入传递给此功能,我不确定有什么风险。 PHP documentation 中的唯一警告是关于在将用户提供的数据传递给函数时使用 escapeshellarg()escapeshellcmd()
      • 谢谢,这是 linux 服务器自己定制项目的最佳答案。如果这个函数在没有用户交互的情况下在项目内部使用,例如通过 cron - 它 100% 安全
      【解决方案7】:

      copy('file.txt', 'compress.zlib://' . 'file.txt.gz'); 见documentation

      【讨论】:

        【解决方案8】:

        这是一个改进的版本。我摆脱了所有嵌套的 if/else 语句,从而降低了圈复杂度,通过异常进行了更好的错误处理,而不是跟踪布尔错误状态,一些类型提示,如果文件具有 gz 扩展名,我将退出已经。它的代码行数有点长,但可读性更强。

        /**
         * Compress a file using gzip
         *
         * Rewritten from Simon East's version here:
         * https://stackoverflow.com/a/22754032/3499843
         *
         * @param string $inFilename Input filename
         * @param int    $level      Compression level (default: 9)
         *
         * @throws Exception if the input or output file can not be opened
         *
         * @return string Output filename
         */
        function gzcompressfile(string $inFilename, int $level = 9): string
        {
            // Is the file gzipped already?
            $extension = pathinfo($inFilename, PATHINFO_EXTENSION);
            if ($extension == "gz") {
                return $inFilename;
            }
        
            // Open input file
            $inFile = fopen($inFilename, "rb");
            if ($inFile === false) {
                throw new \Exception("Unable to open input file: $inFilename");
            }
        
            // Open output file
            $gzFilename = $inFilename.".gz";
            $mode = "wb".$level;
            $gzFile = gzopen($gzFilename, $mode);
            if ($gzFile === false) {
                fclose($inFile);
                throw new \Exception("Unable to open output file: $gzFilename");
            }
        
            // Stream copy
            $length = 512 * 1024; // 512 kB
            while (!feof($inFile)) {
                gzwrite($gzFile, fread($inFile, $length));
            }
        
            // Close files
            fclose($inFile);
            gzclose($gzFile);
        
            // Return the new filename
            return $gzFilename;
        }
        

        【讨论】:

          【解决方案9】:

          压缩文件夹以满足任何人的需要

          function gzCompressFile($source, $level = 9)
          {
              $tarFile = $source . '.tar';
          
              if (is_dir($source)) {
                  $tar = new PharData($tarFile);
                  $files = scandir($source);
                  foreach ($files as $file) {
                      if (is_file($source . '/' . $file)) {
                          $tar->addFile($source . '/' . $file, $file);
                      }
                  }
              }
          
              $dest = $tarFile . '.gz';
              $mode = 'wb' . $level;
              $error = false;
              if ($fp_out = gzopen($dest, $mode)) {
                  if ($fp_in = fopen($tarFile, 'rb')) {
                      while (!feof($fp_in))
                          gzwrite($fp_out, fread($fp_in, 1024 * 512));
                      fclose($fp_in);
                  } else {
                      $error = true;
                  }
                  gzclose($fp_out);
                  unlink($tarFile);
              } else {
                  $error = true;
              }
              if ($error)
                  return false;
              else
                  return $dest;
          }
          

          【讨论】:

            猜你喜欢
            • 2014-07-09
            • 2011-03-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-07-18
            • 1970-01-01
            • 2015-09-10
            • 2015-08-25
            相关资源
            最近更新 更多