zoukankan      html  css  js  c++  java
  • PHP日志压缩下载

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

    由于用到了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':
                    YjcHzip::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 = YjcHzip::getDirSize($entryname);
                $filesize = filesize($entryname);
    
                $files = array(
                    'path' => $d->path,
                    'name' => $entry,
                    'entry' => $entryname,
                    'size' => YjcHzip::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

  • 相关阅读:
    应对https协议的下载方式
    订单峰值激增 230%,Serverless 如何为世纪联华降本超 40%?|双11 云原生实践
    阿里云函数计算发布新功能,支持容器镜像,加速应用 Serverless 进程
    专访阿里云 Serverless 负责人:无服务器不会让后端失业
    从零入门 Serverless | SAE 的远程调试和云端联调
    我在阿里巴巴做 Serverless 云开发平台
    高德最佳实践:Serverless 规模化落地有哪些价值?
    [图论总结1]最大独立集(例题:Code Names)
    Excel导入SQL工具【3.02】
    学习笔记助手【2.01】base1 更新
  • 原文地址:https://www.cnblogs.com/52fhy/p/6249155.html
Copyright © 2011-2022 走看看