PHP日志压缩下载

@date:2017-01-04 16:22:00

主要实现了在后台查看日志列表及打包下载功能。

由于用到了PHP压缩功能,特此记录下。

压缩下载类:
Hzip.php

<?php
/**
 * Created by PhpStorm.
 * @author: YJC
 * @date: 2017/1/4
 */

namespace Yjc;

use ZipArchive;

class Hzip
{
    /**
     * Add files and sub-directories in a folder to zip file.
     * @param string $folder
     * @param ZipArchive $zipFile
     * @param int $exclusiveLength Number of text to be exclusived from the file path.
     */
    private static function folderToZip($folder, &$zipFile, $exclusiveLength) {
        $handle = opendir($folder);
        while (false !== $f = readdir($handle)) {
            if ($f != '.' && $f != '..') {
                $filePath = "$folder/$f";
                // Remove prefix from file path before add to zip.
                $localPath = substr($filePath, $exclusiveLength);
                if (is_file($filePath)) {
                    $zipFile->addFile($filePath, $localPath);
                } elseif (is_dir($filePath)) {
                    // Add sub-directory.
                    $zipFile->addEmptyDir($localPath);
                    self::folderToZip($filePath, $zipFile, $exclusiveLength);
                }
            }
        }
        closedir($handle);
    }

    private static function fileToZip($folder, &$zipFile, $exclusiveLength) {
        $localPath = substr($folder, $exclusiveLength);
        $zipFile->addFile($folder, $localPath);
    }

    /**
     * Zip a folder (include itself).
     * Usage:
     *   HZip::zipDir('/path/to/sourceDir', '/path/to/out.zip');
     *
     * @param string $sourcePath Path of directory to be zip.
     * @param string $outZipPath Path of output zip file.
     */
    public static function zipDir($sourcePath, $outZipPath)
    {
        $pathInfo = pathinfo($sourcePath);
        $parentPath = $pathInfo['dirname'];
        $dirName = $pathInfo['basename'];

        $z = new ZipArchive();
        $z->open($outZipPath, ZipArchive::CREATE);
        $z->addEmptyDir($dirName);

        if(is_dir($sourcePath)){
            self::folderToZip($sourcePath, $z, strlen("$parentPath/"));
        }else{
            self::fileToZip($sourcePath, $z, strlen("$parentPath/"));
        }

        $z->close();
    }

    public static function download($file){

//        $filename = sys_get_temp_dir() ."/log.zip"; //最终生成的文件名(含路径)
        $filename = sys_get_temp_dir() ."/". basename($file) . '.zip'; //最终生成的文件名(含路径)

        self::zipDir($file, $filename);

//        header("Cache-Control: public");
//        header("Content-Description: File Transfer");
//        header("Content-type:  application/octet-stream ");
//        header("Accept-Ranges:  bytes ");
        header('Content-disposition: attachment; filename='.basename($filename)); //文件名
        header("Content-Type: application/zip"); //zip格式的
        header("Content-Transfer-Encoding: binary"); //告诉浏览器,这是二进制文件
        header('Content-Length: '. filesize($filename)); //告诉浏览器,文件大小

        ob_clean();
        flush();

        @readfile($filename);
    }

    /**
     * 转换文件大小
     * @param $fileSize
     * @return string
     */
    public static function convertSize($fileSize) {
        $size = sprintf("%u", $fileSize);
        if($size == 0) {
            return("0 Bytes");
        }
        $sizename = array(" Bytes", " KB", " MB", " GB", " TB", " PB", " EB", " ZB", " YB");
        return round($size/pow(1024, ($i = floor(log($size, 1024)))), 2) . $sizename[$i];
    }

    /**
     * 获取文件夹大小
     * 不建议使用,太慢
     * @param $dir
     * @return int
     */
    public static function getDirSize($dir)
    {
        //避免计算父级目录
        if(stripos($dir, '..')){
            return filesize($dir);
        }

        $sizeResult = 0;
        $handle = opendir($dir);
        while (false!==($FolderOrFile = readdir($handle)))
        {
            if($FolderOrFile != "." && $FolderOrFile != "..")
            {
                if(is_dir("$dir/$FolderOrFile")){
                    $sizeResult += self::getDirSize("$dir/$FolderOrFile");
                }else{
                    $sizeResult += filesize("$dir/$FolderOrFile");
                }
            }
        }
        closedir($handle);
        return $sizeResult;
    }
}
?>

逻辑部分无非就是打开某个目录,然后列出来:

/**
     * 日志管理
     */
    public function LogsList(){

        //默认路径
        $default_dir = APP_PATH . "Logs/";

        //获取路径
        if(isset($_GET['path'])){
            $dirpath =   $_GET['path'];
        }else{
            $dirpath =  $default_dir;
        }

        //路径安全检查
        if(stripos($dirpath, 'Logs') === false){
            $dirpath =  $default_dir;
        }

        //规范化路径
        $dirpath = realpath($dirpath);

        //操作
        $op = empty($_GET['op']) ? 'list' : $_GET['op'];
        switch ($op){
            case 'list':
                $this->LogsListList($dirpath);
                break;
            case 'download':
                \Yjc\Hzip::download($dirpath);
                break;
        }

    }

    private function LogsListList($dirpath){
        //打开路径
        $d  =  dir($dirpath);

        $data = array();
        $data['path'] = $d -> path;
//        $data['log_path'] = getDomain() . "/Logs/http/$date";

        while ( false  !== ( $entry  =  $d -> read ())) {

//            $entryname = realpath($d -> path .'/'. $entry);
            $entryname = $d -> path .'/'. $entry;

//            $filesize = \Yjc\Hzip::getDirSize($entryname);
            $filesize = filesize($entryname);

            $files = array(
                'path' => $d->path,
                'name' => $entry,
                'entry' => $entryname,
                'size' => \Yjc\Hzip::convertSize($filesize),//大小
                'mtime' => filemtime ($entryname),
                'type' => is_dir($entryname) ? 'dir' : 'file',
                'can_down' => in_array($entry, array('.', '..')) ? 0 : 1,
            );
            $filenames[] = $entry;
            $data['entrys'][] = $files;
        }

        //排序
        array_multisort($filenames,SORT_ASC,SORT_STRING, $data['entrys']);

        $d -> close ();

//        dump($data);
        $this->assign('data', $data);
        $this->display(':http_logs_list');
    }

前端把$data展示出来就行啦:

<table class="table table-striped table-bordered table-hover dataTable no-footer"  role="grid" aria-describedby="sample_1_info">
              <thead>
                <tr role="row">
                  <th width="13%">文件名</th>
                  <th width="7%">大小</th>
                  <th width="7%">类型</th>
                  <th width="13%">更新时间</th>
                  <th width="6%">操作</th>
                </tr>
              </thead>
              <tbody>
                <volist name="data.entrys" id="vo">
                <tr class="gradeX odd" role="row">
                    <td>
                  <eq name="vo.type" value="dir">
                        <a href="{:U('Logstats/LogsList')}?path={$vo.entry}">{$vo.name} <i class="fa"></i></a>
                      <else/>
                     {$vo.name}
                  </eq>
                    </td>

                  <td>{$vo.size}</td>
                  <td>{$vo.type}</td>
                  <td>{$vo.mtime|date='Y-m-d H:i:s' , ###}</td>
                  <td>
                      <eq name="vo.can_down" value="1">
                          <a href="{:U('Logstats/LogsList')}?op=download&path={$vo.entry}" target="_blank" class="btn btn-xs green">下载 <i class="fa"></i></a>
                          <else/>

                      </eq>

                  </td>
                </tr>
                </volist>
              </tbody>
            </table>

参考:
1、php如何读取文件夹目录里的文件并按照日期,大小,名称排序 - fzxu_05的个人页面
https://my.oschina.net/wojibuzhu/blog/211674
2、php 文件下载 出现下载文件内容乱码损坏的解决方法 - 微凉 - 博客频道 - CSDN.NET
http://blog.csdn.net/wlqf366/article/details/8744599
3、php实现在线解压、压缩zip文件并下载 | 常亮的技术博客
http://www.diantuo.net/328

Build by Loppo 0.6.14