在PHP中压缩文件夹的内容 [英] Zipping the contents of a folders in PHP

查看:346
本文介绍了在PHP中压缩文件夹的内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在将此信息标记为重复之前,请注意,我已经在SO上搜索答案,而且我发现到目前为止(下面列出)并不是我一直在寻找的。





<这些只是我看过的一些。



我的问题是:我不能使用addFromString,我使用addFile,这是任务的要求。 >

我已经尝试了几种方法,这里是我当前的迭代:

  public function getZippedFiles($ path)
{
$ real_path = WEBROOT_PATH。$ path;

$ files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($ real_path),RecursiveIteratorIterator :: LEAVES_ONLY);

//#创建一个临时文件&打开它
$ tmp_file = tempnam($ real_path,'');
$ zip_file = preg_replace('\.tmp $','.zip',$ tmp_file);

$ zip = new ZipArchive();
$ zip-> open($ zip_file,ZipArchive :: CREATE);

foreach($ files as $ name => $ file)
{
error_log(print_r($ name,true));
error_log(print_r($ file,true));
if(($ file ==。)||($ file ==..))
{
continue;
}

$ file_path = $ file-> getRealPath();
$ zip-> addFile($ file_path);
}

$ zip-> close();
}

当我尝试打开生成的文件时,打开文件夹压缩(压缩)文件夹''无效。



我已经成功地使用addFromString完成任务,如下:

  $ file_path = WEBROOT_PATH。$ path; 
$ files = array();
if(is_dir($ file_path)== true)
{
if($ handle = opendir($ file_path))
{
while(($ file = readdir($ handle))!== false)
{
if(is_dir($ file_path。$ file)== false)
{
$ files [] = $ file_path 。\\。$ file;
}
}

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

//#创建一个临时文件&打开它
$ tmp_file = tempnam($ file_path,'');
$ zip_file = preg_replace('\.tmp $','.zip',$ tmp_file);

$ zip-> open($ zip_file,ZipArchive :: CREATE);

//#循环遍历每个文件
foreach($ files as $ file){

//#下载文件
$ download_file = file_get_contents $ file);

//#将其添加到zip
$ zip-> addFromString(basename($ file),$ download_file);

}

//#close zip
$ zip-> close();
}
}
}

直接从一些示例代码我看到的地方。如果任何人都能指出我的方向,我会非常感谢!



*****更新*****
我添加了一个if这样的结果如下:

  if(!$ zip-> close()){
echofailed写邮政归档;
}

消息被回传,所以很明显问题出在那里。我还检查以确保 $ zip-> open()工作,我已经确认它是打开它没有问题。

解决方案

最后设法使用 addFile 工作。



我创建了一个包含3个函数的帮助类:一个列出目录中的所有文件,1个压缩所有这些文件,1个下载压缩文件:

 <?php 
require_once($ _ SERVER [DOCUMENT_ROOT]。/ config.php);

class FileHelper extends ZipArchive
{
/ **
*列出dir中的文件
*
*此函数需要一个绝对路径作为目标的文件夹。
*该函数将尝试创建一个数组,其中包含目标目录中所有文件(
*除外)的完整路径。和$ ..
*
* @param dir [string]:目标目录的绝对路径
*
* @return result [array]:指向文件的绝对路径数组在目标目录
* /
public static function listDirectory($ dir)
{
$ result = array();
$ root = scandir($ dir);
foreach($ root as $ value){
if($ value ==='。'|| $ value ==='..'){
continue;
}
if(is_file($ dir $ value)){
$ result [] =$ dir $ value;
continue;
}
if(is_dir($ dir $ value)){
$ result [] =$ dir $ value /;
}
foreach(self :: listDirectory($ dir $ value /)as $ value)
{
$ result [] = $ value;
}
}
return $ result;
}

/ **
*压缩和下载文件
*
*此函数需要目录位置作为临时文件的目标, list(array)
*将被压缩并添加到zip文件的绝对文件名。压缩后,
*临时压缩文件将被下载和删除。
*
* @param location [string]:将包含temp文件的目录的绝对路径
* @param file_list [array]:指向需要的文件的绝对路径数组被压缩
*
* @return void
* /
public function downloadZip($ file)
{
$ modules = apache_get_modules
if(in_array('mod_xsendfile',$ modules))//注意,不可能检测到X-SendFile是否打开,我们只能检查模块是否安装。如果X-SendFile安装但关闭,文件下载将不起作用
{
header(Content-Type:application / octet-stream);
header('Content-Disposition:attachment; filename ='。basename($ file)。'');
header(X-Sendfile:.realpath(dirname(__ FILE __))。$ file);

// Apache将处理剩下的事情,因此终止脚本
exit;
}

header(Content-Type:application / octet-stream);
header(Content-Length:。(string)(filesize($ file)));
header('Content-Disposition:attachment; filename ='。basename($ file)。'');
header(Content-Transfer-Encoding:binary);
header(Expires:0);
header(Cache-Control:no-cache,must-revalidate);
header(Cache-Control:private);
header(Pragma:public);

ob_end_clean(); //没有这个,文件将被读入输出缓冲区,破坏大文件上的内存
readfile($ file);
}

/ **
* Zips文件
*
*此函数需要一个目录位置作为临时文件的目标, array)
*绝对文件名,它们将被压缩并添加到一个zip文件中。
*
* @param location [string]:将包含temp文件的目录的绝对路径
* @param file_list [array]:指向需要的文件的绝对路径数组被压缩
*
* @return zip_file [string]:新压缩文件的绝对文件路径
* /
public function zipFile($ location,$ file_list)
{
$ tmp_file = tempnam($ location,'');
$ zip_file = preg_replace('\.tmp $','.zip',$ tmp_file);

$ zip = new ZipArchive();
if($ zip-> open($ zip_file,ZIPARCHIVE :: CREATE)=== true)
{
foreach($ file_list as $ file)
{
if($ file!== $ zip_file)
{
$ zip-> addFile($ file,substr($ file,strlen($ location)));
}
}
$ zip-> close();
}

//删除临时文件
unlink($ tmp_file);

return $ zip_file;
}
}
?>

以下是我调用此类的函数的方法:

  $ location =d:/ some / path / to / file /; 
$ file_list = $ file_helper :: listDirectory($ location);
$ zip_file = $ file_helper-> zipFile($ location,$ file_list);
$ file_helper-> downloadZip($ zip_file);


Before marking this post as a duplicate, please note that I have already searched for answer on SO and the once I've found so far (listed below) haven't been exactly what I've been looking for.

Those are just some of the ones I've looked at.

My problem is this: I can't use addFromString, I have to use addFile, it's a requirement of the task.

I've already tried a couple of ways, here's my current iteration:

public function getZippedFiles($path)
{
    $real_path = WEBROOT_PATH.$path;

    $files = new RecursiveIteratorIterator (new RecursiveDirectoryIterator($real_path), RecursiveIteratorIterator::LEAVES_ONLY);

    //# create a temp file & open it
    $tmp_file = tempnam($real_path,'');
    $zip_file = preg_replace('"\.tmp$"', '.zip', $tmp_file);

    $zip = new ZipArchive();
    $zip->open($zip_file, ZipArchive::CREATE);

    foreach ($files as $name=>$file)
    {
        error_log(print_r($name, true));
        error_log(print_r($file, true));
        if ( ($file == ".") || ($file == "..") )
        {
            continue;
        }

        $file_path = $file->getRealPath();
        $zip->addFile($file_path);
    }

    $zip->close();
}

When I try to open the resulting file, I get told that "Windows cannot open the folder. The Compressed(zipped) Folder '' is invalid."

I've managed to succesfully complete the task using addFromString, like so:

$file_path = WEBROOT_PATH.$path;
    $files = array();
    if (is_dir($file_path) == true)
    {
        if ($handle = opendir($file_path))
        {
            while (($file = readdir($handle)) !== false)
            {
                if (is_dir($file_path.$file) == false)
                {
                    $files[] = $file_path."\\".$file;
                }
            }

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

            //# create a temp file & open it
            $tmp_file = tempnam($file_path,'');
            $zip_file = preg_replace('"\.tmp$"', '.zip', $tmp_file);

            $zip->open($zip_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();
        }
    }
}

The above is mostly just copied straight from some example code I saw somewhere. If anyone can point me in a good direction I'd be very grateful!

***** UPDATE ***** I added an if around the close like this:

if (!$zip->close()) {
    echo "failed writing zip to archive";
}

The message gets echoed out, so obviously the problem is there. I've also checked to make sure the $zip->open() works, and I've confirmed that it is opening it without a problem.

解决方案

Finally managed to get something working using addFile.

I created a helper class that contains 3 functions: one to list all the files in a directory, 1 to zip all those files, and 1 to download the zipped files:

<?php
require_once($_SERVER["DOCUMENT_ROOT"]."/config.php");

class FileHelper extends ZipArchive
{
    /**
     * Lists files in dir
     * 
     * This function expects an absolute path to a folder intended as the target.
     * The function will attempt to create an array containing the full paths to 
     * all files in the target directory, except for . and ..
     * 
     * @param dir [string]    : absolute path to the target directory
     * 
     * @return result [array] : array of absolute paths pointing to files in the target directory
     */
    public static function listDirectory($dir)
    {
        $result = array();
        $root = scandir($dir);
        foreach($root as $value) {
            if($value === '.' || $value === '..') {
                continue;
            }
            if(is_file("$dir$value")) {
                $result[] = "$dir$value";
                continue;
            }
            if(is_dir("$dir$value")) {
                $result[] = "$dir$value/";
            }
            foreach(self::listDirectory("$dir$value/") as $value)
            {
                $result[] = $value;
            }
        }
        return $result;
    }

    /**
     * Zips and downloads files
     * 
     * This function expects a directory location as target for a temp file, and a list(array)
     * of absolute file names that will be compressed and added to a zip file. After compression,
     * the temporary zipped file will be downloaded and deleted.
     * 
     * @param location [string] : absolute path to the directory that will contain the temp file
     * @param file_list [array] : array of absolute paths pointing to files that need to be compressed
     * 
     * @return void
     */
    public function downloadZip($file)
    {
        $modules = apache_get_modules();
        if (in_array('mod_xsendfile', $modules)) // Note, it is not possible to detect if X-SendFile is turned on or not, we can only check if the module is installed. If X-SendFile is installed but turned off, file downloads will not work
        {
            header("Content-Type: application/octet-stream");
            header('Content-Disposition: attachment; filename="'.basename($file).'"');
            header("X-Sendfile: ".realpath(dirname(__FILE__)).$file);

            // Apache will take care of the rest, so terminate the script
            exit;
        }

        header("Content-Type: application/octet-stream");
        header("Content-Length: " .(string)(filesize($file)) );
        header('Content-Disposition: attachment; filename="'.basename($file).'"');
        header("Content-Transfer-Encoding: binary");
        header("Expires: 0");
        header("Cache-Control: no-cache, must-revalidate");
        header("Cache-Control: private");
        header("Pragma: public");

        ob_end_clean(); // Without this, the file will be read into the output buffer which destroys memory on large files
        readfile($file);
    }

    /**
     * Zips files
     * 
     * This function expects a directory location as target for a temp file, and a list(array)
     * of absolute file names that will be compressed and added to a zip file. 
     * 
     * @param location [string]  : absolute path to the directory that will contain the temp file
     * @param file_list [array]  : array of absolute paths pointing to files that need to be compressed
     * 
     * @return zip_file [string] : absolute file path of the freshly zipped file
     */
    public function zipFile($location, $file_list)
    {
        $tmp_file = tempnam($location,'');
        $zip_file = preg_replace('"\.tmp$"', '.zip', $tmp_file);

        $zip = new ZipArchive();
        if ($zip->open($zip_file, ZIPARCHIVE::CREATE) === true)
        {
            foreach ($file_list as $file)
            {
                if ($file !== $zip_file)
                {
                    $zip->addFile($file, substr($file, strlen($location)));
                }
            }
            $zip->close();
        }

        // delete the temporary files
        unlink($tmp_file);

        return $zip_file;
    }
}
?>

Here's how I called this class's functions:

$location = "d:/some/path/to/file/";
$file_list = $file_helper::listDirectory($location);
$zip_file = $file_helper->zipFile($location, $file_list);
$file_helper->downloadZip($zip_file);

这篇关于在PHP中压缩文件夹的内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆