把上面代码保存一个文件它就可以公共调用与修
分类:巴黎人-前端

静态财富文件自动削减并替换来压缩版本(大型网站优化技能)

2015/11/26 · HTML5 · 静态资源

初稿出处: Kelly   

那三回,笔者总括和享用一项大型网址优化本领,那就是在档案的次序中自行削减静态财富文件(css、js),并让网站活动加载压缩后的财富文件。当然,那项手艺在雅虎35条前端优化建议里也可能有记载,但它那只是给出贰个驳斥的方案而已,何况动用的是外表压缩工具去收缩,而在小编的等级次序中,是一贯通过和煦的次序自动化去收缩全部css、js文件,然后让页面一贯加载所减弱后的能源,接下去直接进入正题。

本次实验应用的是PHP脚本语言,版本是PHP5.6,是在LINUX下搭建的情况(网上搭建无论是搭建LAMP依然LNMP的科目都美妙绝伦非常倒霉,后一次作者会计算和享用什么在LINUX下搭建服务器情况的博文,何况搭建的条件必需一遍性搭建成功的)。所采取的框架是CI框架,所运用的沙盘是斯马特y模板引擎。当然了,这个只是自笔者所使用的情况而已,假诺你是PHP开辟者,假诺你要测量试验下这一次试验,那么,作者建议你的PHP版本选用5.4上述,至于框架用什么都以足以的。而固然你不是PHP开采者(你是JSP恐怕是ASP开采者也许是其余开辟者),那么你精通好这一思路后,完全能够在大团结深谙的言语里举办试验测验。

一、原理图

先是笔者画一张思路图,便于大家先掌握。

第一是财富收缩原理图:

巴黎人手机版 1

随着是财富文件替换的规律图:

巴黎人手机版 2

如若大家认真驾驭况且看懂这两张原理图的话,基本上也就调控了自个儿所享用的思路。固然照旧不能够知道的话,接下去作者会结合代码,对以上原理图的每一步进行详尽疏解。

二、思路详细剖判

1.率先是调用该滑坡的艺术,你能够把该措施放在网址所要加载的公共类的地点,举个例子每一遍访谈网址都会调用该滑坡方法进行压缩。当然,这一个只是在开荒条件才会每一次都调用,借使是线上的蒙受,在你的网址发贰回新本子的时候,调用三遍用来生成压缩版的静态能源就可以了。

class MY_Controller extends CI_Controller { public function __construct() { parent::__construct(); //压缩jscss财富文件 $this->compressResHandle(); } /** * 压缩js、css能源文件(优化) * @return [type] [description] */ private function compressResHandle() { $this->load->library('ResMinifier'); //压缩钦赐文件夹下的财富文件 $this->resminifier->compressRes(); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MY_Controller extends CI_Controller {
    public function __construct() {
        parent::__construct();
 
        //压缩jscss资源文件
        $this->compressResHandle();
    }
    /**
     * 压缩js、css资源文件(优化)
     * @return [type] [description]
     */
    private function compressResHandle() {
        $this->load->library('ResMinifier');
        //压缩指定文件夹下的资源文件
        $this->resminifier->compressRes();
    }
}

2.随之就调用了 ResMinifier类里的 compressRes方法。在此间自个儿先附上 ResMinifier这些类的代码,然后方便一步步扩充剖析教学

PHP

<?php defined('BASEPATH') OR exit('No direct script access allowed'); /** * 能源压缩类 */ class ResMinifier { /** 需求收缩的财富目录*/ public $compressResDir = ['css', 'js']; /** 忽略压缩的路子,比方此处是js/icon开端的路线忽略压缩*/ public $compressResIngorePrefix = ['js/icon']; /** 能源根目录*/ public $resRootDir; /** 财富版本文件路线*/ private $resStatePath; public function __construct() { $this->resRootDir = WEBROOT . 'www/'; $this->resStatePath = WEBROOT . 'www/resState.php'; } public function compressRes() { //获取寄存版本的财富文件 $resState = $this->getResState(); $count = 0; //初步遍历必要降低的能源目录 foreach ($this->compressResDir as $resDir) { foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->resRootDir . $resDir , FilesystemIterator::SKIP_DOTS)) as $file) { //获取该财富文件的绝对路径$filePath = str_replace('\', '/', $file->getRealPath()); //获取文件相对路线 $object = substr($filePath, strlen($this->resRootDir)); //计算文件的版本号 $state = $this->_getResStateVersion($filePath); //获取文件的多少个参数值 if (true !== $this->getObjectInfo($object, $minObject, $needCompress, $state, $extension)) { continue; } //压缩文件的相对路线 $minFilePath = str_replace('\', '/', $this->resRootDir. $minObject); //************此处p决断是最重大片段之一*****************// //决断文件是不是存在且已经转移过 if (isset($resState[$object]) && $resState[$object] == $state && isset($resState[$minObject]) && file_exists($minFilePath)) { continue; } //确认保障/www/min/目录可写 $this->_ensureWritableDir(dirname($minFilePath)); if ($needCompress) { $this->compressResFileAndSave($filePath, $minFilePath); } else { copy($filePath, $minFilePath); } $resState[$object] = $state; $resState[$minObject] = ''; $count++; if ($count == 50) { $this->_saveResState($resState); $count = 0; } } } if($count) $this->_saveResState($resState); } public function getObjectInfo($object, &$minObject, &$needCompress, &$state, &$extension) { //获取能源相对路线 $filePath = $this->resRootDir . $object; //决断能源是或不是存在 if (!file_exists($filePath)) return "财富文件海市蜃楼{$filePath}"; //版本号 $state = $this-> _getResStateVersion($filePath); //文件名后缀 $extension = pathinfo($filePath, PATHINFO_EXTENSION); //是还是不是要减弱 $needCompress = true; //判别能源文件是还是不是是以 .min.css或然.min.js结尾的 //此类结尾一般都以已压缩过,比如jquery.min.js,就不用再压缩了 if (str_end_with($object, '.min.'.$extension, true)) { //压缩后的能源寄放路线,放在 /www/min/ 目录下 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state .'.'. $extension; $needCompress = false; } else if (in_array($extension, $this->compressResDir)) { //此处是供给裁减的文件目录 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension; //看看是不是是忽略的门道前缀 foreach ($this->compressResIngorePrefix as $v) { if (str_start_with($object, $v, true)) { $needCompress = false; } } } else { $minObject = 'min/'.$object; $needCompress = false; } return true; } /** * 获取存放财富版本的文件 * 它是放在八个数组里 * $resState = array( * '文件路线' => '对应的本子号', * '文件路线' => '对应的本子号', * '文件路线' => '对应的版本号', * ); * @return [type] [description] */ public function getResState() { if (file_exists($this->resStatePath)) { require $this->resStatePath; return $resState; } return []; } /** * 总括文件的本子号,这么些是基于测算文件MD5散列值获得版本号 * 只要文件内容退换了,所总计获得的散列值就能分歧样 * 用于推断能源文件是否有退换过 * @param [type] $filePath [description] * @return [type] [description] */ public function _getResStateVersion($filePath) { return base_convert(crc32(md5_file($filePath)), 10, 36); } /** * 确认保证目录可写 * @param [type] $dir [description] * @return [type] [description] */ private function _ensureWritableDir($dir) { if (!file_exists($dir)) { @mkdir($dir, 0777, true); @chmod($dir, 0777); } else if (!is_writable($dir)) { @chmod($dir, 0777); if (!is_writable($dir)) { show_error('目录'.$dir.'不可写'); } } } /** * 将缩减后的能源文件写入到/www/min/下去 * @param [type] $filePath [description] * @param [type] $minFilePath [description] * @return [type] [description] */ private function compressResFileAndSave($filePath, $minFilePath) { if (!file_put_contents($minFilePath, $this->compressResFile($filePath))) { //$CI->exceptions->show_exception("写入文件{$minFilePath}败北"); show_error("写入文件{$minFilePath}退步", -1); } } /** * 压缩能源文件 * @param [type] $filePath [description] * @return [type] [description] */ private function compressResFile($filePath) { $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); if ($extension === 'js') { require_once 'JShrink/Minifier.php'; return JShrinkMinifier::minify(file_get_contents($filePath)); } else if ($extension ==='css') { $content = file_get_contents($filePath); $content = preg_replace('!/*[^*]**+([^/][^*]**+)*/!', '', $content); $content = str_replace(["rn", "r", "n"], '', $content); $content = preg_replace('/([{}),;:>])s+/', '$1', $content); $content = preg_replace('/s+([{}),;:>])/', '$1', $content); $content = str_replace(';}', '}', $content); return $content; } else { //$CI->exceptions->show_exception("不援助压缩{extension}文件[$filePath]"); show_error("不协助压缩{extension}文件[$filePath]", -1); } } private function _saveResState($resState) { ksort($resState); $content = "<?phpnn$resState = array(n"; foreach ($resState as $k => $v) { $content .= "t '$k' => '$v',n"; } $content .= ");nn"; file_put_contents($this->resStatePath, $content); } } 点击张开能源压缩类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* 资源压缩类
*/
class ResMinifier {
    /** 需要压缩的资源目录*/
    public $compressResDir = ['css', 'js'];
    /** 忽略压缩的路径,例如此处是js/icon开头的路径忽略压缩*/
    public $compressResIngorePrefix = ['js/icon'];
    /** 资源根目录*/
    public $resRootDir;
    /** 资源版本文件路径*/
    private $resStatePath;
 
    public function __construct() {
        $this->resRootDir = WEBROOT . 'www/';
        $this->resStatePath = WEBROOT . 'www/resState.php';
    }
 
    public function compressRes() {
        //获取存放版本的资源文件
        $resState = $this->getResState();
        $count = 0;
 
        //开始遍历需要压缩的资源目录
        foreach ($this->compressResDir as $resDir) {
            foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->resRootDir . $resDir , FilesystemIterator::SKIP_DOTS)) as $file) {
                //获取该资源文件的绝对路径
                $filePath = str_replace('\', '/', $file->getRealPath());
                //获取文件相对路径
                $object = substr($filePath, strlen($this->resRootDir));
                //计算文件的版本号
                $state = $this->_getResStateVersion($filePath);
 
                //获取文件的几个参数值
                if (true !== $this->getObjectInfo($object, $minObject, $needCompress, $state, $extension)) {
                    continue;
                }
 
                //压缩文件的绝对路径
                $minFilePath = str_replace('\', '/', $this->resRootDir. $minObject);
 
                //************此处p判断是最重要部分之一*****************//
                //判断文件是否存在且已经改动过
                if (isset($resState[$object]) && $resState[$object] == $state && isset($resState[$minObject]) && file_exists($minFilePath)) {
                    continue;
                }
 
                //确保/www/min/目录可写
                $this->_ensureWritableDir(dirname($minFilePath));
 
                if ($needCompress) {
                    $this->compressResFileAndSave($filePath, $minFilePath);
                } else {
                    copy($filePath, $minFilePath);
                }
 
                $resState[$object] = $state;
                $resState[$minObject] = '';
                $count++;
 
                if ($count == 50) {
                    $this->_saveResState($resState);
                    $count = 0;
                }
 
            }
        }
        if($count) $this->_saveResState($resState);
    }
 
    public function getObjectInfo($object, &$minObject, &$needCompress, &$state, &$extension) {
        //获取资源绝对路径
        $filePath = $this->resRootDir . $object;
        //判断资源是否存在
        if (!file_exists($filePath)) return "资源文件不存在{$filePath}";
        //版本号
        $state = $this-> _getResStateVersion($filePath);
        //文件名后缀
        $extension = pathinfo($filePath, PATHINFO_EXTENSION);
        //是否要压缩
        $needCompress = true;
 
        //判断资源文件是否是以 .min.css或者.min.js结尾的
        //此类结尾一般都是已压缩过,例如jquery.min.js,就不必再压缩了
        if (str_end_with($object, '.min.'.$extension, true)) {
            //压缩后的资源存放路径,放在 /www/min/ 目录下
            $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state .'.'. $extension;
            $needCompress = false;
        } else if (in_array($extension, $this->compressResDir)) {
            //此处是需要压缩的文件目录
            $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension;
            //看看是否是忽略的路径前缀
            foreach ($this->compressResIngorePrefix as $v) {
                if (str_start_with($object, $v, true)) {
                    $needCompress = false;
                }
            }
        } else {
            $minObject = 'min/'.$object;
            $needCompress = false;
        }
        return true;
    }
 
    /**
     * 获取存放资源版本的文件
     * 它是放在一个数组里
     * $resState = array(
     *         '文件路径' => '对应的版本号',
     *         '文件路径' => '对应的版本号',
     *         '文件路径' => '对应的版本号',
     *     );
     * @return [type] [description]
     */
    public function getResState() {
        if (file_exists($this->resStatePath)) {
            require $this->resStatePath;
            return $resState;
        }
        return [];
    }
 
    /**
     * 计算文件的版本号,这个是根据计算文件MD5散列值得到版本号
     * 只要文件内容改变了,所计算得到的散列值就会不一样
     * 用于判断资源文件是否有改动过
     * @param  [type] $filePath [description]
     * @return [type]           [description]
     */
    public function _getResStateVersion($filePath) {
        return base_convert(crc32(md5_file($filePath)), 10, 36);
    }
 
    /**
     * 确保目录可写
     * @param  [type] $dir [description]
     * @return [type]      [description]
     */
    private function _ensureWritableDir($dir) {
        if (!file_exists($dir)) {
            @mkdir($dir, 0777, true);
            @chmod($dir, 0777);
        } else if (!is_writable($dir)) {
            @chmod($dir, 0777);
            if (!is_writable($dir)) {
                show_error('目录'.$dir.'不可写');
            }
        }
    }
 
    /**
     * 将压缩后的资源文件写入到/www/min/下去
     * @param  [type] $filePath    [description]
     * @param  [type] $minFilePath [description]
     * @return [type]              [description]
     */
    private function compressResFileAndSave($filePath, $minFilePath) {
        if (!file_put_contents($minFilePath, $this->compressResFile($filePath))) {
 
            //$CI->exceptions->show_exception("写入文件{$minFilePath}失败");
            show_error("写入文件{$minFilePath}失败", -1);
        }
    }
 
    /**
     * 压缩资源文件
     * @param  [type] $filePath [description]
     * @return [type]           [description]
     */
    private function compressResFile($filePath) {
        $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
        if ($extension === 'js') {
            require_once 'JShrink/Minifier.php';
            return JShrinkMinifier::minify(file_get_contents($filePath));
        } else if ($extension ==='css') {
            $content = file_get_contents($filePath);
            $content = preg_replace('!/*[^*]**+([^/][^*]**+)*/!', '', $content);
            $content = str_replace(["rn", "r", "n"], '', $content);
            $content = preg_replace('/([{}),;:>])s+/', '$1', $content);
            $content = preg_replace('/s+([{}),;:>])/', '$1', $content);
            $content = str_replace(';}', '}', $content);
            return $content;
        } else {
            //$CI->exceptions->show_exception("不支持压缩{extension}文件[$filePath]");
            show_error("不支持压缩{extension}文件[$filePath]", -1);
 
        }
    }
 
    private function _saveResState($resState) {
        ksort($resState);
        $content = "<?phpnn$resState = array(n";
        foreach ($resState as $k => $v) {
            $content .= "t '$k' => '$v',n";
        }
        $content .= ");nn";
        file_put_contents($this->resStatePath, $content);
    }
 
}
 
点击打开 资源压缩类

全数类大部分代码小编都加了疏解,方便我们相当的慢精晓。这里本身也会对每一行代码进行解说。

(1)

PHP

/** 供给减小的财富目录*/ public $compressResDir = ['css', 'js']; /** 忽略压缩的门道,比如此处是js/icon开头的门道忽略压缩*/ public $compressResIngorePrefix = ['js/icon']; /** 财富根目录*/ public $resRootDir; /** 财富版本文件路线*/ private $resStatePath; public function __construct() { $this->resRootDir = WEBROOT . 'www/'; $this->resStatePath = WEBROOT . 'www/resState.php'; }

1
2
3
4
5
6
7
8
9
10
11
12
13
/** 需要压缩的资源目录*/
    public $compressResDir = ['css', 'js'];
    /** 忽略压缩的路径,例如此处是js/icon开头的路径忽略压缩*/
    public $compressResIngorePrefix = ['js/icon'];
    /** 资源根目录*/
    public $resRootDir;
    /** 资源版本文件路径*/
    private $resStatePath;
 
    public function __construct() {
        $this->resRootDir = WEBROOT . 'www/';
        $this->resStatePath = WEBROOT . 'www/resState.php';
    }

$compressResDir变量是供给减小的能源目录,假使你有新的拍卖目录,能够在此变量里尽管新的目录名就能够管理。附上自个儿测量检验项指标目录图

巴黎人手机版 3

$compressResIngorePrefix 忽略被削减的路线的门径前有些是该数组变量的字符串,比方有二个财富路线为 js/icon/bg.js可能是js/icon_index.js也许是js/icon.header.js,借使在该数组中参与了 js/icon那个字符串,那么能源路线为js/icon开端的都会被忽略掉,也正是直接跳过,不用压缩。(因为能源文件里总有局地是不必要减小的呗)

$resRootDir寄放财富根目录的

$resStatePath 那个是能源版本文件路线

(2)步入compressRes() 方法,我们先深入分析后面这一段代码

PHP

public function compressRes() { //获取贮存版本的能源文件 $resState = $this->getResState(); $count = 0;

1
2
3
4
public function compressRes() {
        //获取存放版本的资源文件
        $resState = $this->getResState();
        $count = 0;

——————————-调用getResState() 讲解start————————————————————-

此处首先是调用 $this->getResState() 方法来博取存放版本的财富文件,此处先跳到该格局看看是怎么写的,其实就是包涵该文件,然后回到里面存放版本号的数组,大家看注释能够知道该文件里贮存版本号的格式(顺便附上航海用教室让大家看看)

PHP

/** * 获取寄放能源版本的公文 * 它是坐落多少个数组里 * $resState = array( * '文件路线' => '对应的版本号', * '文件路线' => '对应的本子号', * '文件路线' => '对应的本子号', * ); * @return [type] [description] */ public function getResState() { if (file_exists($this->resStatePath)) { require $this->resStatePath; return $resState; } return []; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
     * 获取存放资源版本的文件
     * 它是放在一个数组里
     * $resState = array(
     *         '文件路径' => '对应的版本号',
     *         '文件路径' => '对应的版本号',
     *         '文件路径' => '对应的版本号',
     *     );
     * @return [type] [description]
     */
    public function getResState() {
        if (file_exists($this->resStatePath)) {
            require $this->resStatePath;
            return $resState;
        }
        return [];
    }

(财富版本文件截图:)

巴黎人手机版 4

——————————-调用getResState() 讲解end————————————————————-

继而看compressRes()里的这一段代码

PHP

//初步遍历要求收缩的财富目录 foreach ($this->compressResDir as $resDir) { foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->resRootDir . $resDir , FilesystemIterator::SKIP_DOTS)) as $file) { //获取该能源文件的相对路线$filePath = str_replace('\', '/', $file->getRealPath()); //获取文件相对路线 $object = substr($filePath, strlen($this->resRootDir)); //总计文件的版本号 $state = $this->_getResStateVersion($filePath);

1
2
3
4
5
6
7
8
9
//开始遍历需要压缩的资源目录
        foreach ($this->compressResDir as $resDir) {
            foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->resRootDir . $resDir , FilesystemIterator::SKIP_DOTS)) as $file) {
                //获取该资源文件的绝对路径
                $filePath = str_replace('\', '/', $file->getRealPath());
                //获取文件相对路径
                $object = substr($filePath, strlen($this->resRootDir));
                //计算文件的版本号
                $state = $this->_getResStateVersion($filePath);

先是个遍历的是js和css目录 第一个遍历是将js目录恐怕css目录里的文书都形成路线方式,

比如说获取文件的相对路径 $filePath 的值是那样子的:

/usr/local/apache2/htdocs/project/www/css/home/index.css

而文件的相对路线$object是那样子的 :

css/home/index.css

这里就起来调用$this->_getResStateVersion($filePath)来计量文件的本子号

——————————-调用_getResStateVersion($filePath) 讲解start————————————————————

PHP

/** * 计算文件的版本号,这一个是依赖计算文件MD5散列值获得版本号 * 只要文件内容改动了,所总计获得的散列值就可以区别 * 用于判别财富文件是不是有转移过 * @param [type] $filePath [description] * @return [type] [description] */ public function _getResStateVersion($filePath) { return base_convert(crc32(md5_file($filePath)), 10, 36); }

1
2
3
4
5
6
7
8
9
10
/**
     * 计算文件的版本号,这个是根据计算文件MD5散列值得到版本号
     * 只要文件内容改变了,所计算得到的散列值就会不一样
     * 用于判断资源文件是否有改动过
     * @param  [type] $filePath [description]
     * @return [type]           [description]
     */
    public function _getResStateVersion($filePath) {
        return base_convert(crc32(md5_file($filePath)), 10, 36);
    }

——————————-调用_getResStateVersion($filePath) 讲解end————————————————————-

抑或到版本号后,再看下一段代码,这里起头调用$this->getObjectInfo()方法,这里收获到压缩文件的相对路线$minObject,是还是不是必要压缩$needCompress,版本号$state,文件后缀$extension。

PHP

//获取文件的多少个参数值 if (true !== $this->getObjectInfo($object, $minObject, $needCompress, $state, $extension)) { continue; }

1
2
3
4
//获取文件的几个参数值
                if (true !== $this->getObjectInfo($object, $minObject, $needCompress, $state, $extension)) {
                    continue;
                }

——————————调用$this->getObjectInfo() 讲解start————————————————————

PHP

/** * 获取财富文件有关音讯 * @param [type] $object 财富文件路径(www/css/home/index.css) * @param [type] $minObject 压缩能源文件路径(www/min/css/home/index.ae123a.css) * @param [type] $needCompress 是或不是需求压缩 * @param [type] $state 文件版本号 * @param [type] $extension 文件名后缀 * @return [type] [description] */ public function getObjectInfo($object, &$minObject, &$needCompress, &$state, &$extension) { //获取财富相对路线 $filePath = $this->resRootDir . $object; //判别财富是或不是存在 if (!file_exists($filePath)) return "财富文件海市蜃楼{$filePath}"; //版本号 $state = $this-> _getResStateVersion($filePath); //文件名后缀 $extension = pathinfo($filePath, PATHINFO_EXTENSION); //是还是不是要缩减 $needCompress = true; //推断资源文件是或不是是以 .min.css只怕.min.js结尾的 //此类结尾一般都以已回退过,举个例子jquery.min.js,就不要再压缩了 if (str_end_with($object, '.min.'.$extension, true)) { //压缩后的能源寄放路线,放在 /www/min/ 目录下 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state .'.'. $extension; $needCompress = false; } else if (in_array($extension, $this->compressResDir)) { //此处是索要减弱的文件目录 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension; //看看是还是不是是忽略的门道前缀 foreach ($this->compressResIngorePrefix as $v) { if (str_start_with($object, $v, true)) { $needCompress = false; } } } else { $minObject = 'min/'.$object; $needCompress = false; } return true; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**
     * 获取资源文件相关信息
     * @param  [type] $object       资源文件路径 (www/css/home/index.css)
     * @param  [type] $minObject    压缩资源文件路径 (www/min/css/home/index.ae123a.css)
     * @param  [type] $needCompress 是否需要压缩
     * @param  [type] $state        文件版本号
     * @param  [type] $extension    文件名后缀
     * @return [type]               [description]
     */
    public function getObjectInfo($object, &$minObject, &$needCompress, &$state, &$extension) {
        //获取资源绝对路径
        $filePath = $this->resRootDir . $object;
        //判断资源是否存在
        if (!file_exists($filePath)) return "资源文件不存在{$filePath}";
        //版本号
        $state = $this-> _getResStateVersion($filePath);
        //文件名后缀
        $extension = pathinfo($filePath, PATHINFO_EXTENSION);
        //是否要压缩
        $needCompress = true;
 
        //判断资源文件是否是以 .min.css或者.min.js结尾的
        //此类结尾一般都是已压缩过,例如jquery.min.js,就不必再压缩了
        if (str_end_with($object, '.min.'.$extension, true)) {
            //压缩后的资源存放路径,放在 /www/min/ 目录下
            $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state .'.'. $extension;
            $needCompress = false;
        } else if (in_array($extension, $this->compressResDir)) {
            //此处是需要压缩的文件目录
            $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension;
            //看看是否是忽略的路径前缀
            foreach ($this->compressResIngorePrefix as $v) {
                if (str_start_with($object, $v, true)) {
                    $needCompress = false;
                }
            }
        } else {
            $minObject = 'min/'.$object;
            $needCompress = false;
        }
        return true;
    }

那个方法里的每一行代码基本上都有注释了,所以就不一句句进行批注了,这里关键看上边包车型大巴推断部分:

if (str_end_with($object, ‘.min.’.$extension, true)) 那几个论断是相比较能源文件路线字串尾巴部分是还是不是以 .min.$extension 结尾,比方是 jquery.min.js,这种文件本来便是
调整和裁减过的文件,所以就不用再开展削减管理了, $minObject 那一个变量贮存的是缩减后的财富文件路线。
此间附上str_end_with()函数的代码:

PHP

/** * 剖断 subject 是或不是以 search结尾, 参数钦赐是还是不是忽略大小写 * @param [type] $subject [description] * @param [type] $search [description] * @param boolean $ignore_case [description] * @return [type] [description] */ function str_end_with($subject, $search, $ignore_case = false) { $len2 = strlen($search); if (0 === $len2) return true; $len1 = strlen($subject); if ($len2 > $len1) return false; if ($ignore_case) { return 0 === strcmp(substr($subject, $len1 - $len2), $search); } else { return 0 === strcasecmp(substr($subject, $len1 - $len2), $search); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
     * 判断 subject 是否以 search结尾, 参数指定是否忽略大小写
     * @param  [type]  $subject     [description]
     * @param  [type]  $search      [description]
     * @param  boolean $ignore_case [description]
     * @return [type]               [description]
     */
    function str_end_with($subject, $search, $ignore_case = false) {
        $len2 = strlen($search);
        if (0 === $len2) return true;
        $len1 = strlen($subject);
        if ($len2 > $len1) return false;
        if ($ignore_case) {
            return 0 === strcmp(substr($subject, $len1 - $len2), $search);
        } else {
            return 0 === strcasecmp(substr($subject, $len1 - $len2), $search);
        }
    }

if (in_array($extension, $this->compressResDir),那些论断正是是还是不是是需求管理的三个目录里的。

然后中间的foreach ($this->compressResIngorePrefix as $v) { if (str_start_with($object, $v, true)) { $needCompress = false; } }

那个是决断是不是是以$this->compressResIngorePrefix属性定义的前底部分字串起始的路线,是的话就大体压缩该能源文件。

剖断到最后else 正是注解该财富文件没有要求降低了,最终是回到$minObject,$needCompress,$state,$extension那多少个变量。

——————————-调用$this->getObjectInfo() 讲解end————————————————————-

到此地继续回来看 compressRes()方法里面包车型客车代码

PHP

//压缩文件的相对路线 $minFilePath = str_replace('\', '/', $this->resRootDir. $minObject); //************此处p判定是最珍视片段之一*****************// //剖断文件是不是存在且已经转移过 if (isset($resState[$object]) && $resState[$object] == $state && isset($resState[$minObject]) && file_exists($minFilePath)) { continue; }

1
2
3
4
5
6
7
8
//压缩文件的绝对路径
                $minFilePath = str_replace('\', '/', $this->resRootDir. $minObject);
 
                //************此处p判断是最重要部分之一*****************//
                //判断文件是否存在且已经改动过
                if (isset($resState[$object]) && $resState[$object] == $state && isset($resState[$minObject]) && file_exists($minFilePath)) {
                    continue;
                }

这段代码首先是拼接出压缩文件的绝对路线,

随之上面那些推断是主要的有的,通过这些论断就足以清楚该财富文件是不是被转移过,假使退换过的话,就再次对该财富文件进行压缩,假使没改换过,就继续管理下二个能源文件。看这里的剖断:isset($resState[$object]) && $resState[$object] == $state,那么些判定正是决断该文件路线是不是留存  何况文件中对应的版本号和计量出的版本号是或不是还一致;isset($resState[$minObject]) &&file_exists($minFilePath),这些是决断压缩文件路线是还是不是存在,并且该压缩文件是不是真实存在目录中。

看下一段代码,若是能走到这一有个别,表明当前的那么些能源文件是被转移过的(代码修改过),那么此时就对文本举办压缩操作了

PHP

//确定保证/www/min/目录可写 $this->_ensureWritableDir(dirname($minFilePath)); if ($needCompress) { $this->compressResFileAndSave($filePath, $minFilePath); } else { copy($filePath, $minFilePath); }

1
2
3
4
5
6
7
8
//确保/www/min/目录可写
                $this->_ensureWritableDir(dirname($minFilePath));
 
                if ($needCompress) {
                    $this->compressResFileAndSave($filePath, $minFilePath);
                } else {
                    copy($filePath, $minFilePath);
                }

$this->_ensureWritableDir(),此方法是要保管新成立的www/min目录是可写的,这里附上代码:

——————————-调用$this->_ensureWritableDir() 讲解start————————————————————-

PHP

/** * 确定保障目录可写 * @param [type] $dir [description] * @return [type] [description] */ private function _ensureWritableDir($dir) { if (!file_exists($dir)) { @mkdir($dir, 0777, true); @chmod($dir, 0777); } else if (!is_writable($dir)) { @chmod($dir, 0777); if (!is_writable($dir)) { show_error('目录'.$dir.'不可写'); } } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
     * 确保目录可写
     * @param  [type] $dir [description]
     * @return [type]      [description]
     */
    private function _ensureWritableDir($dir) {
        if (!file_exists($dir)) {
            @mkdir($dir, 0777, true);
            @chmod($dir, 0777);
        } else if (!is_writable($dir)) {
            @chmod($dir, 0777);
            if (!is_writable($dir)) {
                show_error('目录'.$dir.'不可写');
            }
        }
    }

——————————-调用$this->_ensureWritableDir() 讲解end————————————————————-

if ($needCompress),那一个剖断财富文件是或不是必要减小,供给的话调用$this->compressResFileAndSave($filePath, $minFilePath);无需的话,直接复制文件到压缩文件路线 copy($filePath, $minFilePath);

先看$this->compressResFileAndSave()

——————————-调用$this->compressResFileAndSave() 讲解start————————————————————-

PHP

/** * 将滑坡后的财富文件写入到/www/min/下去 * @param [type] $filePath [description] * @param [type] $minFilePath [description] * @return [type] [description] */ private function compressResFileAndSave($filePath, $minFilePath) { if (!file_put_contents($minFilePath, $this->compressResFile($filePath))) { //$CI->exceptions->show_exception("写入文件{$minFilePath}失败"); show_error("写入文件{$minFilePath}战败", -1); } } /** * 压缩财富文件 * @param [type] $filePath [description] * @return [type] [description] */ private function compressResFile($filePath) { $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); if ($extension === 'js') { require_once 'JShrink/Minifier.php'; return JShrinkMinifier::minify(file_get_contents($filePath)); } else if ($extension ==='css') { $content = file_get_contents($filePath); $content = preg_replace('!/*[^*]**+([^/][^*]**+)*/!', '', $content); $content = str_replace(["rn", "r", "n"], '', $content); $content = preg_replace('/([{}),;:>])s+/', '$1', $content); $content = preg_replace('/s+([{}),;:>])/', '$1', $content); $content = str_replace(';}', '}', $content); return $content; } else { //$CI->exceptions->show_exception("不援助压缩{extension}文件[$filePath]"); show_error("不帮衬压缩{extension}文件[$filePath]", -1); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
     * 将压缩后的资源文件写入到/www/min/下去
     * @param  [type] $filePath    [description]
     * @param  [type] $minFilePath [description]
     * @return [type]              [description]
     */
    private function compressResFileAndSave($filePath, $minFilePath) {
        if (!file_put_contents($minFilePath, $this->compressResFile($filePath))) {
 
            //$CI->exceptions->show_exception("写入文件{$minFilePath}失败");
            show_error("写入文件{$minFilePath}失败", -1);
        }
    }
 
    /**
     * 压缩资源文件
     * @param  [type] $filePath [description]
     * @return [type]           [description]
     */
    private function compressResFile($filePath) {
        $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
        if ($extension === 'js') {
            require_once 'JShrink/Minifier.php';
            return JShrinkMinifier::minify(file_get_contents($filePath));
        } else if ($extension ==='css') {
            $content = file_get_contents($filePath);
            $content = preg_replace('!/*[^*]**+([^/][^*]**+)*/!', '', $content);
            $content = str_replace(["rn", "r", "n"], '', $content);
            $content = preg_replace('/([{}),;:>])s+/', '$1', $content);
            $content = preg_replace('/s+([{}),;:>])/', '$1', $content);
            $content = str_replace(';}', '}', $content);
            return $content;
        } else {
            //$CI->exceptions->show_exception("不支持压缩{extension}文件[$filePath]");
            show_error("不支持压缩{extension}文件[$filePath]", -1);
 
        }
    }

先削减,再将核减后的剧情写入到 压缩文件路线里去。

大家先看下这几个压缩方法:

$this->compressResFile($filePath); 此方法中分两类压缩,第一类时对js文件进行削减,第二类的对css文件进行压缩。先说js压缩,这里是调用二个JShrink的类,它

二个用来压缩js文件的PHP类,百度得以找到,调用那个类的minify()这些主意就能够减小了;而css的回降利用正则替换成压缩,把这么些空格换行什么的都去掉。到此就减弱成功

了,然后再将减小后的财富写入到相应的压缩文件路线里去。

——————————-调用$this->compressResFileAndSave() 讲解end————————————————————-

紧接着继续看compressRes()那几个法子里的代码,这里起先就是保存新的版本号到$resState数组里 $object=>$state,还应该有正是新的缩减路线$minObject,而那边$count++的效果与利益是,当那么些轮回49遍就将 $resState这一个数组写入一次到 resState.php文件里,这里是由于严谨思考而已,如若你不加那个$count的管理这一部分也足以,最终写入二遍就行了。

PHP

$resState[$object] = $state; $resState[$minObject] = ''; $count++; if ($count == 50) { $this->_saveResState($resState); $count = 0; } } } if($count) $this->_saveResState($resState);

1
2
3
4
5
6
7
8
9
10
11
12
$resState[$object] = $state;
                $resState[$minObject] = '';
                $count++;
 
                if ($count == 50) {
                    $this->_saveResState($resState);
                    $count = 0;
                }
 
            }
        }
        if($count) $this->_saveResState($resState);

这里看$this->_saveResState($resState),这几个主意正是将$resState数组写入到resState.php文件里去的艺术。

——————————-调用$this->_saveResState($resState) 讲解start————————————————————-

PHP

private function _saveResState($resState) { ksort($resState); $content = "<?phpnn$resState = array(n"; foreach ($resState as $k => $v) { $content .= "t '$k' => '$v',n"; } $content .= ");nn"; file_put_contents($this->resStatePath, $content); }

1
2
3
4
5
6
7
8
9
private function _saveResState($resState) {
        ksort($resState);
        $content = "<?phpnn$resState = array(n";
        foreach ($resState as $k => $v) {
            $content .= "t '$k' => '$v',n";
        }
        $content .= ");nn";
        file_put_contents($this->resStatePath, $content);
    }

——————————-调用$this->_saveResState($resState) 讲解end————————————————————-

拍卖完后,看看所生成的文本,这里三个文书会有五个本子,旧版本从未有过去除掉,在开拓境遇下删不删除都没难题,这里怎么不删除旧版本的压缩文件,那就提到到在更新多少个应用服务器代码时所要注意的难题里。在此小编就多批注一点吗,轻巧地举例吗,一般大型项目中的静态财富和模板文件是布局在差别的机器集群上的,上线的进程中,静态财富和页面文件的配置时间间隔可能会相当短,对于二个大型网络应用来讲就是在多少个比非常小的时辰间隔内,都有极大或者出现新客商访问,假使旧版本的静态财富删除了,但新本子的静态财富还没安插到位,那么顾客就加载不到该静态能源,结果同理可得,所以,一般情形下大家会保留旧版本的静态能源,然后等具有片段安顿造成了,再经过一定的剧本删除掉也没涉及,其实,这几个不必删除也是足以的,你思虑,三个项目发一回版本,才会调用一回能源文件裁减方法,它只会对修改过的公文进行生成新版本号的静态文件而已。那么些就看个人的做法了。

巴黎人手机版 5

大家得以张开看看,上面这几个就是削减后的文本的代码了,文件原大小为16K,压缩后大约少了5K,以后是11K,压缩比大概是2/3,假使在大型项目中,一个复杂点的页面会有比异常的大的静态财富文件要加载,通过此措施,大大地提升了加载的快慢。(大概有些朋友认为压缩个几K可能十几K算什么,完全能够忽略,其实作者想说的是,当你在大型项目中优化项指标时候,能够减弱几K的代码,也给网站的天性提升了一大截)

巴黎人手机版 6

到此,能源减少管理就分析实现了。其实,有分明基础的心上人,能够直接看作者享受的要命代码就足以了,如若驾驭不了,再看自个儿下边这一步步的深入分析讲授,作者是居于能看过来此博客的爱人,无论本领是好只怕是稍弱,都能看懂,所以才对代码一步步地扩充解析教学。(希望各位多多援救四哥)

————————————————————————————————————————-

  1. 接下去正是上课如何替换压缩后的能源文件了。

这个到Home.php

PHP

<?php defined('BASEPATH') OR exit('No direct script access allowed'); class Home extends MY_Controller { public function index() { $this->smartyData['test'] = 111; //那么些暗中认可是加载 www/css/home/index.css文件 $this->addResLink('index.css'); //这些默许是加载www/js/jquery.all.min.js文件 $this->addResLink('/jquery.all.min.js'); //这一个暗中同意是加载www/js/index.js文件 $this->addResLink('index.js'); $this->displayView('home/index.tpl'); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
 
class Home extends MY_Controller {
    public function index() {
        $this->smartyData['test'] = 111;
        //这个默认是加载 www/css/home/index.css文件
        $this->addResLink('index.css');
        //这个默认是加载www/js/jquery.all.min.js文件
        $this->addResLink('/jquery.all.min.js');
        //这个默认是加载www/js/index.js文件
        $this->addResLink('index.js');
        $this->displayView('home/index.tpl');
    }
}

地点有加载多个财富文件,大家先看看$this->addResLink();那一个法子,那几个法子放在My_Controller.php里:

PHP

/** * 能源路线 * @param [type] $filePath [description] */ protected function addResLink($filePath) { list($filePath, $query) = explode('?', $filePath . '?'); $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); foreach ($this->_resLink as $v) { if (false === array_search($filePath, $this->_resLink[$extension])) { $this->_resLink[$extension][] = $query == null ? $filePath : $filePath .'?'. $query; } } return $this; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
     * 资源路径
     * @param [type] $filePath [description]
     */
    protected function addResLink($filePath) {
        list($filePath, $query) = explode('?', $filePath . '?');
        $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
        foreach ($this->_resLink as $v) {
            if (false === array_search($filePath, $this->_resLink[$extension])) {
                $this->_resLink[$extension][] = $query == null ? $filePath : $filePath .'?'. $query;
            }
        }
 
        return $this;
    }

这边境海关键是推断了能源文件是css依然js,然后将其贮存在 $this->_resLink那本性情里。

那便是说这里作者就先附上My_Controller.php那么些父类的全体代码吧

PHP

<?php defined('BASEPATH') OR exit('No direct script access allowed'); class MY_Controller extends CI_Controller { public function __construct() { parent::__construct(); //压缩jscss能源文件 $this->compressResHandle(); } //==========================使用SMARTY模板引擎================================// /* Smarty母版页文件路径 */ protected $masterPage = 'default.tpl'; /* 视图像和文字件路线*/ protected $smartyView; /* 要赋值给smarty视图的数码*/ protected $smartyData = []; /* 能源文件*/ protected $_resLink = ['js'=>[], 'css'=>[]]; /** * 使用母版页输出一个视图 * @return [type] [description] */ protected function displayView($viewName = null, $masterPage = null) { //为空则选拔默许母版 if ($masterPage == null) $masterPage = $this->masterPage; //获取视图的输出内容 $viewContent = $this->_fetchView($this->smartyData, $viewName, $masterPage); $output = ''; //添加css Link foreach ($this->_resLink['css'] as $v) { $output .= res_link($v); } //内容部分 $output .= $viewContent; //尾巴部分增加js 链接 foreach ($this->_resLink['js'] as $v) { $output .= res_link($v); } //发送最终输出结果以及服务器的 HTTP 头到浏览器 $this->output->_display($output); return $output; } private function _fetchView($smartyData, &$viewName, &$masterPage) { if ($viewName == null) $viewName = $this->smartyView; if (empty($this->smarty)) { require_once SMARTY_DI福睿斯.'斯马特y.class.php'; $this->smarty = new 斯马特y(); $this->smarty->setCompileDir(APPPATH . 'cache/'); $this->smarty->setCacheDir(应用软件PATH . 'cache/'); } //设置视图真实路线 $this->_getViewDir(true, $viewName, $masterPage, $templateDir); foreach ($smartyData as $k => $v) { $this->smarty->assign($k, $v); } if (empty($masterPage)) { return $this->smarty->fetch($viewName); } else { $this->smarty->assign('VIEW_MAIN', $viewName); return $this->smarty->fetch($masterPage); } } /** * 能源路线 * @param [type] $filePath [description] */ protected function addResLink($filePath) { list($filePath, $query) = explode('?', $filePath . '?'); $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); foreach ($this->_resLink as $v) { if (false === array_search($filePath, $this->_resLink[$extension])) { $this->_resLink[$extension][] = $query == null ? $filePath : $filePath .'?'. $query; } } return $this; } private function _getViewDir($setTemplateDir, &$viewName, &$masterPage = null, &$templateDir) { if ('/' === $viewName[0]) $viewName = substr($viewName, 1); //是或不是选拔模板,有,则路由到 /views/master_page/*****.tpl下去 if ($masterPage) { $masterPage = '/' === $masterPage[0] ? substr($masterPage, 1) : ('master_page' .'/'. $masterPage); } //是或不是设置模板目录 if ($setTemplateDir) { $templateDir = VIEWPATH; $this->smarty->setTemplateDir($templateDir); } } /** * 压缩js、css能源文件(优化) * @return [type] [description] */ private function compressResHandle() { $this->load->library('Res迷你fier'); //压缩钦定文件夹下的能源文件 $this->resminifier->compressRes(); } } 点击打开 My_Controller.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
 
class MY_Controller extends CI_Controller {
    public function __construct() {
        parent::__construct();
 
        //压缩jscss资源文件
        $this->compressResHandle();
    }
 
    //==========================使用SMARTY模板引擎================================//
    /* Smarty母版页文件路径 */
    protected $masterPage = 'default.tpl';
    /* 视图文件路径*/
    protected $smartyView;
    /* 要赋值给smarty视图的数据*/
    protected $smartyData = [];
    /* 资源文件*/
    protected $_resLink = ['js'=>[], 'css'=>[]];
 
    /**
     * 使用母版页输出一个视图
     * @return [type] [description]
     */
    protected function displayView($viewName = null, $masterPage = null) {
        //为空则选用默认母版
        if ($masterPage == null) $masterPage = $this->masterPage;
        //获取视图的输出内容
        $viewContent = $this->_fetchView($this->smartyData, $viewName, $masterPage);
 
        $output = '';
 
        //添加css Link
        foreach ($this->_resLink['css'] as $v) {
            $output .= res_link($v);
        }
 
        //内容部分
        $output .= $viewContent;
        //尾部添加js 链接
        foreach ($this->_resLink['js'] as $v) {
            $output .= res_link($v);
        }
        //发送最终输出结果以及服务器的 HTTP 头到浏览器
 
        $this->output->_display($output);
        return $output;
    }
 
    private function _fetchView($smartyData, &$viewName, &$masterPage) {
        if ($viewName == null) $viewName = $this->smartyView;
 
        if (empty($this->smarty)) {
            require_once SMARTY_DIR.'Smarty.class.php';
            $this->smarty = new Smarty();
            $this->smarty->setCompileDir(APPPATH . 'cache/');
            $this->smarty->setCacheDir(APPPATH . 'cache/');
        }
 
        //设置视图真实路径
        $this->_getViewDir(true, $viewName, $masterPage, $templateDir);
 
        foreach ($smartyData as $k => $v) {
            $this->smarty->assign($k, $v);
        }
 
        if (empty($masterPage)) {
            return $this->smarty->fetch($viewName);
        } else {
            $this->smarty->assign('VIEW_MAIN', $viewName);
            return $this->smarty->fetch($masterPage);
        }
    }
 
    /**
     * 资源路径
     * @param [type] $filePath [description]
     */
    protected function addResLink($filePath) {
        list($filePath, $query) = explode('?', $filePath . '?');
        $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
        foreach ($this->_resLink as $v) {
            if (false === array_search($filePath, $this->_resLink[$extension])) {
                $this->_resLink[$extension][] = $query == null ? $filePath : $filePath .'?'. $query;
            }
        }
 
        return $this;
    }
 
    private function _getViewDir($setTemplateDir, &$viewName, &$masterPage = null, &$templateDir) {
        if ('/' === $viewName[0]) $viewName = substr($viewName, 1);
 
        //是否使用模板,有,则路由到 /views/master_page/*****.tpl下去
        if ($masterPage) {
            $masterPage = '/' === $masterPage[0] ? substr($masterPage, 1) : ('master_page' .'/'. $masterPage);
        }
 
        //是否设置模板目录
        if ($setTemplateDir) {
            $templateDir = VIEWPATH;
            $this->smarty->setTemplateDir($templateDir);
        }
    }
 
    /**
     * 压缩js、css资源文件(优化)
     * @return [type] [description]
     */
    private function compressResHandle() {
        $this->load->library('ResMinifier');
        //压缩指定文件夹下的资源文件
        $this->resminifier->compressRes();
    }
}
 
点击打开 My_Controller.php

打字与印刷出来 $this->_resLink那特个性的构造是那样子的:

PHP

Array ( [js] => Array ( [0] => /jquery.all.min.js [1] => index.js ) [css] => Array ( [0] => index.css ) )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Array
(
    [js] => Array
        (
            [0] => /jquery.all.min.js
            [1] => index.js
        )
 
    [css] => Array
        (
            [0] => index.css
        )
 
)

再重返Home.php里面调用 $this->displayView(‘home/index.tpl’);

笔者们看这些方式:

PHP

/** * 使用母版页输出二个视图 * @return [type] [description] */ protected function displayView($viewName = null, $masterPage = null) { //为空则接纳暗许母版 if ($masterPage == null) $masterPage = $this->masterPage; //获取视图的输出内容 $viewContent = $this->_fetchView($this->smartyData, $viewName, $masterPage); $output = ''; //添加css Link foreach ($this->_resLink['css'] as $v) { $output .= res_link($v); } //内容部分 $output .= $viewContent; //尾部增多js 链接 foreach ($this->_resLink['js'] as $v) { $output .= res_link($v); } //发送最后输出结果以及服务器的 HTTP 头到浏览器 $this->output->_display($output); return $output; } private function _fetchView($smartyData, &$viewName, &$masterPage) { if ($viewName == null) $viewName = $this->smartyView; if (empty($this->smarty)) { require_once SMARTY_DI索罗德.'斯马特y.class.php'; $this->smarty = new Smarty(); $this->smarty->setCompileDir(应用软件PATH . 'cache/'); $this->smarty->setCacheDir(APPPATH . 'cache/'); } //设置视图真实路线 $this->_getViewDir(true, $viewName, $masterPage, $templateDir); foreach ($smartyData as $k => $v) { $this->smarty->assign($k, $v); } if (empty($masterPage)) { return $this->smarty->fetch($viewName); } else { $this->smarty->assign('VIEW_MAIN', $viewName); return $this->smarty->fetch($masterPage); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**
     * 使用母版页输出一个视图
     * @return [type] [description]
     */
    protected function displayView($viewName = null, $masterPage = null) {
        //为空则选用默认母版
        if ($masterPage == null) $masterPage = $this->masterPage;
        //获取视图的输出内容
        $viewContent = $this->_fetchView($this->smartyData, $viewName, $masterPage);
 
        $output = '';
 
        //添加css Link
        foreach ($this->_resLink['css'] as $v) {
            $output .= res_link($v);
        }
 
        //内容部分
        $output .= $viewContent;
        //尾部添加js 链接
        foreach ($this->_resLink['js'] as $v) {
            $output .= res_link($v);
        }
        //发送最终输出结果以及服务器的 HTTP 头到浏览器
 
        $this->output->_display($output);
        return $output;
    }
 
    private function _fetchView($smartyData, &$viewName, &$masterPage) {
        if ($viewName == null) $viewName = $this->smartyView;
 
        if (empty($this->smarty)) {
            require_once SMARTY_DIR.'Smarty.class.php';
            $this->smarty = new Smarty();
            $this->smarty->setCompileDir(APPPATH . 'cache/');
            $this->smarty->setCacheDir(APPPATH . 'cache/');
        }
 
        //设置视图真实路径
        $this->_getViewDir(true, $viewName, $masterPage, $templateDir);
 
        foreach ($smartyData as $k => $v) {
            $this->smarty->assign($k, $v);
        }
 
        if (empty($masterPage)) {
            return $this->smarty->fetch($viewName);
        } else {
            $this->smarty->assign('VIEW_MAIN', $viewName);
            return $this->smarty->fetch($masterPage);
        }
    }

这一段代码未有一部分便是调用了斯玛特y模板引擎的剧情,这几个关于斯马特y的学识笔者就不讲了,大家能够本身百度,这里最首要讲 res_link() 那些函数,就是经过那几个函数来开展能源文件替换的。先看那些函数的代码:

PHP

/** * 输出 HttpHead 中的财富总是。 css/js 自动推断真实路线 * @param string 文件路线 * @return string */ function res_link($file) { $file = res_path($file, $extension); if ($extension === 'css') { return '<link rel="stylesheet" type="text/css" href="' . $file . '"/>'; } else if ($extension === 'js') { return '<script type="text/javascript" src="'.$file.'"></script>'; } else { return false; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
     * 输出 HttpHead 中的资源连接。 css/js 自动判断真实路径
     * @param  string  文件路径
     * @return string      
     */
    function res_link($file) {
        $file = res_path($file, $extension);
 
        if ($extension === 'css') {
           return '<link rel="stylesheet" type="text/css" href="' . $file . '"/>';
        } else if ($extension === 'js') {
            return '<script type="text/javascript" src="'.$file.'"></script>';
        } else {
            return false;
        }
    }

这里最首要便是 res_path() 函数了,这几个函数能自行路由财富的真人真事路线。比如:index.css = > css/home/index.css

该函数最重视的一个效果是替换能源的压缩版本。

直接看代码:

PHP

/** * 智能路由能源实际路线 * @param string 路径 * @param string 扩展名 * @return string 真实路线 */ function res_path($file, &$extension) { //检查是还是不是留存询问字符串 list($file, $query) = explode('?', $file . '?'); //获得扩展名 $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION)); // $file = str_replace('\', '/', $file); //取妥善前调控器名 global $class; if ($class == null) exit('can not get class name'); $className = strtolower($class); //此处的条条框框是那般: //举个例子,假设不加 / ,Home调控器对应的格式是: index.css,那么 此处的路线会产生css/home/index.css //要是有 / ,调整器的格式能够是 /main.css,那么这里的路线会形成 css/main.css(公用的css类) if ('/' !== $file[0]) { //index.css => css/home/index.css $object = $extension .'/'. $className .'/' . $file; } else { // /css/main.css 或许 /main.css => css/main.css $object = substr($file, 1); //若object是 main.css ,则自动抬高 扩充名目录 => css/main.css if (0 !== strncasecmp($extension, $object, strlen($extension))) { $object = $extension . '/' . $object; } } //能源真实路线 $filepath = WEBROOT.'www/'.$object; //替换压缩版本,那部分逻辑与公事收缩逻辑对应 if (in_array($extension, array('css', 'js'))) { if(!str_start_with($object, 'min/') && file_exists(APPPATH.'libraries/ResMinifier.php')) { require_once APPPATH.'libraries/ResMinifier.php'; $resminifier = new ResMinifier(); //获取寄放能源版本的文本的数组变量 $resState = $resminifier->getResState(); //总计取妥贴前文件版本号 $state = $resminifier->_getResStateVersion($filepath); //剖断该版本号是还是不是留存 if (isset($resState[$object])) { //剖断是还是不是是.min.css或.min.js结尾 if (str_end_with($object, '.min.'.$extension)) { //将版本号拼接上去,然后拿走min的文件路线 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state . '.' . $extension; } else { //将版本号拼接上去,然后拿走min的公文路线 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension; } //推断min的门道是还是不是留存在$resState里面 if (isset($resState[$minObject])) { $object = $minObject; $query = ''; } } } $file = RES_BASE_URL . $object; } return ($query == null) ? $file : ($file .'?'. $query); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
     * 智能路由资源真实路径
     * @param  string      路径
     * @param  string      扩展名
     * @return string       真实路径
     */
    function res_path($file, &$extension) {
        //检查是否存在查询字符串
        list($file, $query) = explode('?', $file . '?');
        //取得扩展名
        $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
        //
        $file = str_replace('\', '/', $file);
        //取得当前控制器名
        global $class;
        if ($class == null) exit('can not get class name');
        $className = strtolower($class);
 
        //此处的规则是这样:
        //例如,如果不加 / ,Home控制器对应的格式是: index.css,那么 此处的路径会变成css/home/index.css
        //假如有 / ,控制器的格式可以是 /main.css,那么此处的路径会变成 css/main.css(公用的css类)
        if ('/' !== $file[0]) {
            //index.css => css/home/index.css
            $object = $extension .'/'. $className .'/' . $file;
        } else {
            // /css/main.css 或者 /main.css => css/main.css
            $object = substr($file, 1);
 
            //若object是 main.css ,则自动加上 扩展名目录 => css/main.css
            if (0 !== strncasecmp($extension, $object, strlen($extension))) {
                $object = $extension . '/' . $object;
            }
        }
        //资源真实路径
        $filepath = WEBROOT.'www/'.$object;
 
        //替换压缩版本,这部分逻辑与文件压缩逻辑对应
        if (in_array($extension, array('css', 'js'))) {
            if(!str_start_with($object, 'min/') && file_exists(APPPATH.'libraries/ResMinifier.php')) {
                require_once APPPATH.'libraries/ResMinifier.php';
                $resminifier = new ResMinifier();
                //获取存放资源版本的文件的数组变量
                $resState = $resminifier->getResState();
                //计算得到当前文件版本号
                $state = $resminifier->_getResStateVersion($filepath);
                //判断该版本号是否存在
                if (isset($resState[$object])) {
                    //判断是否是.min.css或.min.js结尾
                    if (str_end_with($object, '.min.'.$extension)) {
                        //将版本号拼接上去,然后得到min的文件路径
                        $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state . '.' . $extension;
                    } else {
                        //将版本号拼接上去,然后得到min的文件路径
                        $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension;
                    }
                    //判断min的路径是否存在在$resState里面
                     if (isset($resState[$minObject])) {
                        $object = $minObject;
                        $query = '';
                     }
                }
 
            }
 
            $file = RES_BASE_URL . $object;
        }
 
        return ($query == null) ? $file : ($file .'?'. $query);
 
    }

代码基本上都给了讲授,方便大家轻松去领略,前面一部分是智能路线css、js财富的不二秘技,后边一部分是替换压缩版本,这一部分的逻辑其实和能源减弱这里的逻辑基本等同,便是通过财富文件路线,举行决断和管理,最终收获财富的回降版本的门道,最终就将财富的减弱版本的路径重返去,放在'<link rel=”stylesheet” type=”text/css” href=”‘ . $file . ‘”/>’里面。那样  ,就成功地将财富文件路径替换来了收缩版本的财富文件路径,何况在模板输出时,输出的是减掉后的能源文件。

到此,能源替换的源委就到此疏解截至。而整一项才干也深入分析到此。

三、总结

在此间小编聚集地附着本博文讲授中的几个文本代码:

Home.php

PHP

<?php defined('BASEPATH') OR exit('No direct script access allowed'); class Home extends MY_Controller { public function index() { $this->smartyData['test'] = 111; //这一个暗中同意是加载 www/css/home/index.css文件 $this->addResLink('index.css'); //那一个暗中认可是加载www/js/jquery.all.min.js文件 $this->addResLink('/jquery.all.min.js'); //那几个私下认可是加载www/js/index.js文件 $this->addResLink('index.js'); $this->displayView('home/index.tpl'); } } 点击展开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
 
class Home extends MY_Controller {
    public function index() {
        $this->smartyData['test'] = 111;
        //这个默认是加载 www/css/home/index.css文件
        $this->addResLink('index.css');
        //这个默认是加载www/js/jquery.all.min.js文件
        $this->addResLink('/jquery.all.min.js');
        //这个默认是加载www/js/index.js文件
        $this->addResLink('index.js');
        $this->displayView('home/index.tpl');
    }
}
 
点击打开

My_Controller.php

PHP

<?php defined('BASEPATH') OR exit('No direct script access allowed'); class MY_Controller extends CI_Controller { public function __construct() { parent::__construct(); //压缩jscss能源文件 $this->compressResHandle(); } //==========================使用SMARTY模板引擎================================// /* 斯马特y母版页文件路线 */ protected $masterPage = 'default.tpl'; /* 视图像和文字件路线*/ protected $smartyView; /* 要赋值给smarty视图的数据*/ protected $smartyData = []; /* 资源文件*/ protected $_resLink = ['js'=>[], 'css'=>[]]; /** * 使用母版页输出叁个视图 * @return [type] [description] */ protected function displayView($viewName = null, $masterPage = null) { //为空则选取默许母版 if ($masterPage == null) $masterPage = $this->masterPage; //获取视图的出口内容 $viewContent = $this->_fetchView($this->smartyData, $viewName, $masterPage); $output = ''; //添加css Link foreach ($this->_resLink['css'] as $v) { $output .= res_link($v); } //内容部分 $output .= $viewContent; //尾巴部分增加js 链接 foreach ($this->_resLink['js'] as $v) { $output .= res_link($v); } //发送最后输出结果以及服务器的 HTTP 头到浏览器 $this->output->_display($output); return $output; } private function _fetchView($smartyData, &$viewName, &$masterPage) { if ($viewName == null) $viewName = $this->smartyView; if (empty($this->smarty)) { require_once SMARTY_DISportage.'斯马特y.class.php'; $this->smarty = new 斯马特y(); $this->smarty->setCompileDir(应用程式PATH . 'cache/'); $this->smarty->setCacheDir(APPPATH . 'cache/'); } //设置视图真实路线 $this->_getViewDir(true, $viewName, $masterPage, $templateDir); foreach ($smartyData as $k => $v) { $this->smarty->assign($k, $v); } if (empty($masterPage)) { return $this->smarty->fetch($viewName); } else { $this->smarty->assign('VIEW_MAIN', $viewName); return $this->smarty->fetch($masterPage); } } /** * 财富路线 * @param [type] $filePath [description] */ protected function addResLink($filePath) { list($filePath, $query) = explode('?', $filePath . '?'); $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); foreach ($this->_resLink as $v) { if (false === array_search($filePath, $this->_resLink[$extension])) { $this->_resLink[$extension][] = $query == null ? $filePath : $filePath .'?'. $query; } } return $this; } private function _getViewDir($setTemplateDir, &$viewName, &$masterPage = null, &$templateDir) { if ('/' === $viewName[0]) $viewName = substr($viewName, 1); //是不是使用模板,有,则路由到 /views/master_page/*****.tpl下去 if ($masterPage) { $masterPage = '/' === $masterPage[0] ? substr($masterPage, 1) : ('master_page' .'/'. $masterPage); } //是不是设置模板目录 if ($setTemplateDir) { $templateDir = VIEWPATH; $this->smarty->setTemplateDir($templateDir); } } /** * 压缩js、css财富文件(优化) * @return [type] [description] */ private function compressResHandle() { $this->load->library('ResMinifier'); //压缩钦点文件夹下的能源文件 $this->resminifier->compressRes(); } } 点击张开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
 
class MY_Controller extends CI_Controller {
    public function __construct() {
        parent::__construct();
 
        //压缩jscss资源文件
        $this->compressResHandle();
    }
 
    //==========================使用SMARTY模板引擎================================//
    /* Smarty母版页文件路径 */
    protected $masterPage = 'default.tpl';
    /* 视图文件路径*/
    protected $smartyView;
    /* 要赋值给smarty视图的数据*/
    protected $smartyData = [];
    /* 资源文件*/
    protected $_resLink = ['js'=>[], 'css'=>[]];
 
    /**
     * 使用母版页输出一个视图
     * @return [type] [description]
     */
    protected function displayView($viewName = null, $masterPage = null) {
        //为空则选用默认母版
        if ($masterPage == null) $masterPage = $this->masterPage;
        //获取视图的输出内容
        $viewContent = $this->_fetchView($this->smartyData, $viewName, $masterPage);
 
        $output = '';
 
        //添加css Link
        foreach ($this->_resLink['css'] as $v) {
            $output .= res_link($v);
        }
 
        //内容部分
        $output .= $viewContent;
        //尾部添加js 链接
        foreach ($this->_resLink['js'] as $v) {
            $output .= res_link($v);
        }
        //发送最终输出结果以及服务器的 HTTP 头到浏览器
 
        $this->output->_display($output);
        return $output;
    }
 
    private function _fetchView($smartyData, &$viewName, &$masterPage) {
        if ($viewName == null) $viewName = $this->smartyView;
 
        if (empty($this->smarty)) {
            require_once SMARTY_DIR.'Smarty.class.php';
            $this->smarty = new Smarty();
            $this->smarty->setCompileDir(APPPATH . 'cache/');
            $this->smarty->setCacheDir(APPPATH . 'cache/');
        }
 
        //设置视图真实路径
        $this->_getViewDir(true, $viewName, $masterPage, $templateDir);
 
        foreach ($smartyData as $k => $v) {
            $this->smarty->assign($k, $v);
        }
 
        if (empty($masterPage)) {
            return $this->smarty->fetch($viewName);
        } else {
            $this->smarty->assign('VIEW_MAIN', $viewName);
            return $this->smarty->fetch($masterPage);
        }
    }
 
    /**
     * 资源路径
     * @param [type] $filePath [description]
     */
    protected function addResLink($filePath) {
        list($filePath, $query) = explode('?', $filePath . '?');
        $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
        foreach ($this->_resLink as $v) {
            if (false === array_search($filePath, $this->_resLink[$extension])) {
                $this->_resLink[$extension][] = $query == null ? $filePath : $filePath .'?'. $query;
            }
        }
 
        return $this;
    }
 
    private function _getViewDir($setTemplateDir, &$viewName, &$masterPage = null, &$templateDir) {
        if ('/' === $viewName[0]) $viewName = substr($viewName, 1);
 
        //是否使用模板,有,则路由到 /views/master_page/*****.tpl下去
        if ($masterPage) {
            $masterPage = '/' === $masterPage[0] ? substr($masterPage, 1) : ('master_page' .'/'. $masterPage);
        }
 
        //是否设置模板目录
        if ($setTemplateDir) {
            $templateDir = VIEWPATH;
            $this->smarty->setTemplateDir($templateDir);
        }
    }
 
    /**
     * 压缩js、css资源文件(优化)
     * @return [type] [description]
     */
    private function compressResHandle() {
        $this->load->library('ResMinifier');
        //压缩指定文件夹下的资源文件
        $this->resminifier->compressRes();
    }
}
 
点击打开

ResMinifier.php

PHP

<?php defined('BASEPATH') OR exit('No direct script access allowed'); /** * 能源压缩类 */ class ResMinifier { /** 须求收缩的财富目录*/ public $compressResDir = ['css', 'js']; /** 忽略压缩的路线,比方此处是js/icon开端的门径忽略压缩*/ public $compressResIngorePrefix = ['js/icon']; /** 财富根目录*/ public $resRootDir; /** 能源版本文件路线*/ private $resStatePath; public function __construct() { $this->resRootDir = WEBROOT . 'www/'; $this->resStatePath = WEBROOT . 'www/resState.php'; } public function compressRes() { //获取存放版本的能源文件 $resState = $this->getResState(); $count = 0; //初阶遍历须要减小的财富目录 foreach ($this->compressResDir as $resDir) { foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->resRootDir . $resDir , FilesystemIterator::SKIP_DOTS)) as $file) { //获取该财富文件的相对路线$file帕特h = str_replace('\', '/', $file->getRealPath()); //获取文件相对路线 $object = substr($filePath, strlen($this->resRootDir)); //总括文件的本子号 $state = $this->_getResStateVersion($filePath); //获取文件的多少个参数值 if (true !== $this->getObjectInfo($object, $minObject, $needCompress, $state, $extension)) { continue; } //压缩文件的绝对路径 $minFilePath = str_replace('\', '/', $this->resRootDir. $minObject); //************此处p决断是最重大多数之一*****************// //判别文件是还是不是存在且已经济体改成过 if (isset($resState[$object]) && $resState[$object] == $state && isset($resState[$minObject]) && file_exists($minFile帕特h)) { continue; } //确定保障/www/min/目录可写 $this->_ensureWritableDir(dirname($minFilePath)); if ($needCompress) { $this->compressResFileAndSave($filePath, $minFilePath); } else { copy($filePath, $minFilePath); } $resState[$object] = $state; $resState[$minObject] = ''; $count++; if ($count == 50) { $this->_saveResState($resState); $count = 0; } } } if($count) $this->_saveResState($resState); } /** * 获取财富文件有关新闻 * @param [type] $object 能源文件路线 (www/css/home/index.css) * @param [type] $minObject 压缩财富文件路线 (www/min/css/home/index.ae123a.css) * @param [type] $needCompress 是不是须要压缩 * @param [type] $state 文件版本号 * @param [type] $extension 文件名后缀 * @return [type] [description] */ public function getObjectInfo($object, &$minObject, &$needCompress, &$state, &$extension) { //获取财富相对路线 $file帕特h = $this->resRootDir . $object; //判定财富是或不是存在 if (!file_exists($filePath)) return "财富文件不真实{$file帕特h}"; //版本号 $state = $this-> _getResStateVersion($filePath); //文件名后缀 $extension = pathinfo($filePath, PATHINFO_EXTENSION); //是或不是要减少$needCompress = true; //剖断财富文件是还是不是是以 .min.css大概.min.js结尾的 //此类结尾一般皆以已缩减过,比如jquery.min.js,就不用再压缩了 if (str_end_with($object, '.min.'.$extension, true)) { //压缩后的财富寄存路线,放在 /www/min/ 目录下 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state .'.'. $extension; $needCompress = false; } else if (in_array($extension, $this->compressResDir)) { //此处是内需减小的文件目录 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension; //看看是还是不是是忽略的路线前缀 foreach ($this->compressResIngorePrefix as $v) { if (str_start_with($object, $v, true)) { $needCompress = false; } } } else { $minObject = 'min/'.$object; $needCompress = false; } return true; } /** * 获取存放财富版本的文件 * 它是投身四个数组里 * $resState = array( * '文件路线' => '对应的本子号', * '文件路径' => '对应的版本号', * '文件路线' => '对应的本子号', * ); * @return [type] [description] */ public function getResState() { if (file_exists($this->resStatePath)) { require $this->resStatePath; return $resState; } return []; } /** * 统计文件的版本号,那些是依附统计文件MD5散列值获得版本号 * 只要文件内容改动了,所总括获得的散列值就能不均等 * 用于判别财富文件是或不是有变动过 * @param [type] $filePath [description] * @return [type] [description] */ public function _getResStateVersion($filePath) { return base_convert(crc32(md5_file($filePath)), 10, 36); } /** * 确认保障目录可写 * @param [type] $dir [description] * @return [type] [description] */ private function _ensureWritableDir($dir) { if (!file_exists($dir)) { @mkdir($dir, 0777, true); @chmod($dir, 0777); } else if (!is_writable($dir)) { @chmod($dir, 0777); if (!is_writable($dir)) { show_error('目录'.$dir.'不可写'); } } } /** * 将减少后的财富文件写入到/www/min/下去 * @param [type] $filePath [description] * @param [type] $minFilePath [description] * @return [type] [description] */ private function compressResFileAndSave($filePath, $minFilePath) { if (!file_put_contents($minFilePath, $this->compressResFile($filePath))) { //$CI->exceptions->show_exception("写入文件{$minFilePath}失利"); show_error("写入文件{$minFilePath}战败", -1); } } /** * 压缩能源文件 * @param [type] $filePath [description] * @return [type] [description] */ private function compressResFile($filePath) { $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); if ($extension === 'js') { require_once 'JShrink/Minifier.php'; return JShrinkMinifier::minify(file_get_contents($filePath)); } else if ($extension ==='css') { $content = file_get_contents($filePath); $content = preg_replace('!/*[^*]**+([^/][^*]**+)*/!', '', $content); $content = str_replace(["rn", "r", "n"], '', $content); $content = preg_replace('/([{}),;:>])s+/', '$1', $content); $content = preg_replace('/s+([{}),;:>])/', '$1', $content); $content = str_replace(';}', '}', $content); return $content; } else { //$CI->exceptions->show_exception("不协助压缩{extension}文件[$filePath]"); show_error("不帮衬压缩{extension}文件[$filePath]", -1); } } private function _saveResState($resState) { ksort($resState); $content = "<?phpnn$resState = array(n"; foreach ($resState as $k => $v) { $content .= "t '$k' => '$v',n"; } $content .= ");nn"; file_put_contents($this->resStatePath, $content); } } 点击张开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* 资源压缩类
*/
class ResMinifier {
    /** 需要压缩的资源目录*/
    public $compressResDir = ['css', 'js'];
    /** 忽略压缩的路径,例如此处是js/icon开头的路径忽略压缩*/
    public $compressResIngorePrefix = ['js/icon'];
    /** 资源根目录*/
    public $resRootDir;
    /** 资源版本文件路径*/
    private $resStatePath;
 
    public function __construct() {
        $this->resRootDir = WEBROOT . 'www/';
        $this->resStatePath = WEBROOT . 'www/resState.php';
    }
 
    public function compressRes() {
        //获取存放版本的资源文件
        $resState = $this->getResState();
        $count = 0;
 
        //开始遍历需要压缩的资源目录
        foreach ($this->compressResDir as $resDir) {
            foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->resRootDir . $resDir , FilesystemIterator::SKIP_DOTS)) as $file) {
                //获取该资源文件的绝对路径
                $filePath = str_replace('\', '/', $file->getRealPath());
 
                //获取文件相对路径
                $object = substr($filePath, strlen($this->resRootDir));
 
                //计算文件的版本号
                $state = $this->_getResStateVersion($filePath);
 
                //获取文件的几个参数值
                if (true !== $this->getObjectInfo($object, $minObject, $needCompress, $state, $extension)) {
                    continue;
                }
 
                //压缩文件的绝对路径
                $minFilePath = str_replace('\', '/', $this->resRootDir. $minObject);
 
                //************此处p判断是最重要部分之一*****************//
                //判断文件是否存在且已经改动过
                if (isset($resState[$object]) && $resState[$object] == $state && isset($resState[$minObject]) && file_exists($minFilePath)) {
                    continue;
                }
 
                //确保/www/min/目录可写
                $this->_ensureWritableDir(dirname($minFilePath));
 
                if ($needCompress) {
                    $this->compressResFileAndSave($filePath, $minFilePath);
                } else {
                    copy($filePath, $minFilePath);
                }
 
                $resState[$object] = $state;
                $resState[$minObject] = '';
                $count++;
 
                if ($count == 50) {
                    $this->_saveResState($resState);
                    $count = 0;
                }
 
            }
        }
        if($count) $this->_saveResState($resState);
    }
 
    /**
     * 获取资源文件相关信息
     * @param  [type] $object       资源文件路径 (www/css/home/index.css)
     * @param  [type] $minObject    压缩资源文件路径 (www/min/css/home/index.ae123a.css)
     * @param  [type] $needCompress 是否需要压缩
     * @param  [type] $state        文件版本号
     * @param  [type] $extension    文件名后缀
     * @return [type]               [description]
     */
    public function getObjectInfo($object, &$minObject, &$needCompress, &$state, &$extension) {
        //获取资源绝对路径
        $filePath = $this->resRootDir . $object;
        //判断资源是否存在
        if (!file_exists($filePath)) return "资源文件不存在{$filePath}";
        //版本号
        $state = $this-> _getResStateVersion($filePath);
        //文件名后缀
        $extension = pathinfo($filePath, PATHINFO_EXTENSION);
        //是否要压缩
        $needCompress = true;
 
        //判断资源文件是否是以 .min.css或者.min.js结尾的
        //此类结尾一般都是已压缩过,例如jquery.min.js,就不必再压缩了
        if (str_end_with($object, '.min.'.$extension, true)) {
            //压缩后的资源存放路径,放在 /www/min/ 目录下
            $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state .'.'. $extension;
            $needCompress = false;
        } else if (in_array($extension, $this->compressResDir)) {
            //此处是需要压缩的文件目录
            $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension;
            //看看是否是忽略的路径前缀
            foreach ($this->compressResIngorePrefix as $v) {
                if (str_start_with($object, $v, true)) {
                    $needCompress = false;
                }
            }
        } else {
            $minObject = 'min/'.$object;
            $needCompress = false;
        }
        return true;
    }
 
    /**
     * 获取存放资源版本的文件
     * 它是放在一个数组里
     * $resState = array(
     *         '文件路径' => '对应的版本号',
     *         '文件路径' => '对应的版本号',
     *         '文件路径' => '对应的版本号',
     *     );
     * @return [type] [description]
     */
    public function getResState() {
        if (file_exists($this->resStatePath)) {
            require $this->resStatePath;
            return $resState;
        }
        return [];
    }
 
    /**
     * 计算文件的版本号,这个是根据计算文件MD5散列值得到版本号
     * 只要文件内容改变了,所计算得到的散列值就会不一样
     * 用于判断资源文件是否有改动过
     * @param  [type] $filePath [description]
     * @return [type]           [description]
     */
    public function _getResStateVersion($filePath) {
        return base_convert(crc32(md5_file($filePath)), 10, 36);
    }
 
    /**
     * 确保目录可写
     * @param  [type] $dir [description]
     * @return [type]      [description]
     */
    private function _ensureWritableDir($dir) {
        if (!file_exists($dir)) {
            @mkdir($dir, 0777, true);
            @chmod($dir, 0777);
        } else if (!is_writable($dir)) {
            @chmod($dir, 0777);
            if (!is_writable($dir)) {
                show_error('目录'.$dir.'不可写');
            }
        }
    }
 
    /**
     * 将压缩后的资源文件写入到/www/min/下去
     * @param  [type] $filePath    [description]
     * @param  [type] $minFilePath [description]
     * @return [type]              [description]
     */
    private function compressResFileAndSave($filePath, $minFilePath) {
        if (!file_put_contents($minFilePath, $this->compressResFile($filePath))) {
 
            //$CI->exceptions->show_exception("写入文件{$minFilePath}失败");
            show_error("写入文件{$minFilePath}失败", -1);
        }
    }
 
    /**
     * 压缩资源文件
     * @param  [type] $filePath [description]
     * @return [type]           [description]
     */
    private function compressResFile($filePath) {
        $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
        if ($extension === 'js') {
            require_once 'JShrink/Minifier.php';
            return JShrinkMinifier::minify(file_get_contents($filePath));
        } else if ($extension ==='css') {
            $content = file_get_contents($filePath);
            $content = preg_replace('!/*[^*]**+([^/][^*]**+)*/!', '', $content);
            $content = str_replace(["rn", "r", "n"], '', $content);
            $content = preg_replace('/([{}),;:>])s+/', '$1', $content);
            $content = preg_replace('/s+([{}),;:>])/', '$1', $content);
            $content = str_replace(';}', '}', $content);
            return $content;
        } else {
            //$CI->exceptions->show_exception("不支持压缩{extension}文件[$filePath]");
            show_error("不支持压缩{extension}文件[$filePath]", -1);
 
        }
    }
 
    private function _saveResState($resState) {
        ksort($resState);
        $content = "<?phpnn$resState = array(n";
        foreach ($resState as $k => $v) {
            $content .= "t '$k' => '$v',n";
        }
        $content .= ");nn";
        file_put_contents($this->resStatePath, $content);
    }
 
}
 
点击打开

Common.php

PHP

<?php /** * 输出 HttpHead 中的能源总是。 css/js 自动推断真实路径 * @param string 文件路径 * @return string */ function res_link($file) { $file = res_path($file, $extension); if ($extension === 'css') { return '<link rel="stylesheet" type="text/css" href="' . $file . '"/>'; } else if ($extension === 'js') { return '<script type="text/javascript" src="'.$file.'"></script>'; } else { return false; } } /** * 智能路由能源实际路线 * @param string 路径 * @param string 扩展名 * @return string 真实路径 */ function res_path($file, &$extension) { //检查是不是存在询问字符串 list($file, $query) = explode('?', $file . '?'); //取得扩张名 $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION)); // $file = str_replace('\', '/', $file); //取稳当前调整器名 global $class; if ($class == null) exit('can not get class name'); $className = strtolower($class); //此处的平整是这么: //比如,假使不加 / ,Home调控器对应的格式是: index.css,那么 此处的路线会变成css/home/index.css //借使有 / ,调节器的格式能够是 /main.css,那么这里的路线会造成 css/main.css(公用的css类) if ('/' !== $file[0]) { //index.css => css/home/index.css $object = $extension .'/'. $className .'/' . $file; } else { // /css/main.css 可能 /main.css => css/main.css $object = substr($file, 1); //若object是 main.css ,则自动抬高 扩大名目录 => css/main.css if (0 !== strncasecmp($extension, $object, strlen($extension))) { $object = $extension . '/' . $object; } } //财富真实路线 $filepath = WEBROOT.'www/'.$object; //替换压缩版本,这有的逻辑与公事减弱逻辑对应 if (in_array($extension, array('css', 'js'))) { if(!str_start_with($object, 'min/') && file_exists(APPPATH.'libraries/ResMinifier.php')) { require_once 应用软件PATH.'libraries/ResMinifier.php'; $resminifier = new ResMinifier(); //获取贮存财富版本的文件的数组变量 $resState = $resminifier->getResState(); //总计取伏贴前文件版本号 $state = $resminifier->_getResStateVersion($filepath); //判别该版本号是还是不是留存 if (isset($resState[$object])) { //剖断是或不是是.min.css或.min.js结尾 if (str_end_with($object, '.min.'.$extension)) { //将版本号拼接上去,然后拿走min的文本路线 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state . '.' . $extension; } else { //将版本号拼接上去,然后拿走min的文书路线 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension; } //剖断min的不二等秘书籍是或不是留存在$resState里面 if (isset($resState[$minObject])) { $object = $minObject; $query = ''; } } } $file = RES_BASE_URL . $object; } return ($query == null) ? $file : ($file .'?'. $query); } /** * 决断 subject 是还是不是以 search先导, 参数内定是还是不是忽略大小写 * @param [type] $subject [description] * @param [type] $search [description] * @param boolean $ignore_case [description] * @return [type] [description] */ function str_start_with($subject, $search, $ignore_case = false) { $len2 = strlen($search); if (0 === $len2) return true; $len1 = strlen($subject); if ($len1 < $len2) return false; if ($ignore_case) { return 0 === strncmp($subject, $search, $len2); } else { return 0 === strncasecmp($subject, $search, $len2); } } /** * 判断 subject 是不是以 search结尾, 参数内定是否忽略大小写 * @param [type] $subject [description] * @param [type] $search [description] * @param boolean $ignore_case [description] * @return [type] [description] */ function str_end_with($subject, $search, $ignore_case = false) { $len2 = strlen($search); if (0 === $len2) return true; $len1 = strlen($subject); if ($len2 > $len1) return false; if ($ignore_case) { return 0 === strcmp(substr($subject, $len1 - $len2), $search); } else { return 0 === strcasecmp(substr($subject, $len1 - $len2), $search); } } 点击张开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<?php
    /**
     * 输出 HttpHead 中的资源连接。 css/js 自动判断真实路径
     * @param  string  文件路径
     * @return string      
     */
    function res_link($file) {
        $file = res_path($file, $extension);
 
        if ($extension === 'css') {
           return '<link rel="stylesheet" type="text/css" href="' . $file . '"/>';
        } else if ($extension === 'js') {
            return '<script type="text/javascript" src="'.$file.'"></script>';
        } else {
            return false;
        }
    }
 
    /**
     * 智能路由资源真实路径
     * @param  string      路径
     * @param  string      扩展名
     * @return string       真实路径
     */
    function res_path($file, &$extension) {
        //检查是否存在查询字符串
        list($file, $query) = explode('?', $file . '?');
        //取得扩展名
        $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
        //
        $file = str_replace('\', '/', $file);
        //取得当前控制器名
        global $class;
        if ($class == null) exit('can not get class name');
        $className = strtolower($class);
 
        //此处的规则是这样:
        //例如,如果不加 / ,Home控制器对应的格式是: index.css,那么 此处的路径会变成css/home/index.css
        //假如有 / ,控制器的格式可以是 /main.css,那么此处的路径会变成 css/main.css(公用的css类)
        if ('/' !== $file[0]) {
            //index.css => css/home/index.css
            $object = $extension .'/'. $className .'/' . $file;
        } else {
            // /css/main.css 或者 /main.css => css/main.css
            $object = substr($file, 1);
 
            //若object是 main.css ,则自动加上 扩展名目录 => css/main.css
            if (0 !== strncasecmp($extension, $object, strlen($extension))) {
                $object = $extension . '/' . $object;
            }
        }
        //资源真实路径
        $filepath = WEBROOT.'www/'.$object;
 
        //替换压缩版本,这部分逻辑与文件压缩逻辑对应
        if (in_array($extension, array('css', 'js'))) {
            if(!str_start_with($object, 'min/') && file_exists(APPPATH.'libraries/ResMinifier.php')) {
                require_once APPPATH.'libraries/ResMinifier.php';
                $resminifier = new ResMinifier();
                //获取存放资源版本的文件的数组变量
                $resState = $resminifier->getResState();
                //计算得到当前文件版本号
                $state = $resminifier->_getResStateVersion($filepath);
                //判断该版本号是否存在
                if (isset($resState[$object])) {
                    //判断是否是.min.css或.min.js结尾
                    if (str_end_with($object, '.min.'.$extension)) {
                        //将版本号拼接上去,然后得到min的文件路径
                        $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state . '.' . $extension;
                    } else {
                        //将版本号拼接上去,然后得到min的文件路径
                        $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension;
                    }
                    //判断min的路径是否存在在$resState里面
                     if (isset($resState[$minObject])) {
                        $object = $minObject;
                        $query = '';
                     }
                }
 
            }
 
            $file = RES_BASE_URL . $object;
        }
 
        return ($query == null) ? $file : ($file .'?'. $query);
 
    }
 
    /**
     * 判断 subject 是否以 search开头, 参数指定是否忽略大小写
     * @param  [type]  $subject     [description]
     * @param  [type]  $search      [description]
     * @param  boolean $ignore_case [description]
     * @return [type]               [description]
     */
    function str_start_with($subject, $search, $ignore_case = false) {
        $len2 = strlen($search);
        if (0 === $len2) return true;
        $len1 = strlen($subject);
        if ($len1 < $len2) return false;
        if ($ignore_case) {
            return 0 === strncmp($subject, $search, $len2);
        } else {
            return 0 === strncasecmp($subject, $search, $len2);
        }
    }
 
    /**
     * 判断 subject 是否以 search结尾, 参数指定是否忽略大小写
     * @param  [type]  $subject     [description]
     * @param  [type]  $search      [description]
     * @param  boolean $ignore_case [description]
     * @return [type]               [description]
     */
    function str_end_with($subject, $search, $ignore_case = false) {
        $len2 = strlen($search);
        if (0 === $len2) return true;
        $len1 = strlen($subject);
        if ($len2 > $len1) return false;
        if ($ignore_case) {
            return 0 === strcmp(substr($subject, $len1 - $len2), $search);
        } else {
            return 0 === strcasecmp(substr($subject, $len1 - $len2), $search);
        }
    }
 
点击打开

$resState.php(里面包车型大巴代码是自动生成的)

XHTML

<?php $resState = array( 'css/home/index.css' => 'gwy933', 'js/echarts-all.min.js' => 'wqrf1c', 'js/home/index.js' => 's2z6f5', 'js/icon.js' => 'pgcyih', 'js/icon_home.js' => 'zhl9iu', 'js/ion.rangeSlider.min.js' => 'akq381', 'js/jquery-ui-autocomplete.js' => '8nzacv', 'js/jquery-ui.min.js' => 'i6tw8z', 'js/jquery.all.min.js' => 'd2w76v', 'js/jquery.city.js' => 'toxdrf', 'js/jquery.easydropdown.min.js' => '2ni3i0', 'js/jquery.matrix.js' => '3vrqkk', 'js/jquery.mobile.all.min.js' => 'ernu7r', 'js/jquery.qrcode.min.js' => 'yuhnsj', 'js/jquery.tinyscrollbar.min.js' => 'oakk3c', 'js/mobiscroll.custom.min.js' => 'kn8h2e', 'js/store.min.js' => 'n50jwr', 'js/swiper.animate1.0.2.min.js' => 'mm27zc', 'js/swiper.min.js' => 'jicwhh', 'min/css/home/index.6a4e83eb.css' => '', 'min/css/home/index.gwy933.css' => '', 'min/css/home/index.puzbnf.css' => '', 'min/css/home/index.thv8x7.css' => '', 'min/js/echarts-all.76025ee0.js' => '', 'min/js/echarts-all.wqrf1c.js' => '', 'min/js/home/index.65363d41.js' => '', 'min/js/home/index.s2z6f5.js' => '', 'min/js/icon.5bbd4db9.js' => '', 'min/js/icon.pgcyih.js' => '', 'min/js/icon_home.7fe74076.js' => '', 'min/js/icon_home.zhl9iu.js' => '', 'min/js/ion.rangeSlider.261d8ed1.js' => '', 'min/js/ion.rangeSlider.akq381.js' => '', 'min/js/jquery-ui-autocomplete.1f3bb62f.js' => '', 'min/js/jquery-ui-autocomplete.8nzacv.js' => '', 'min/js/jquery-ui.418e9683.js' => '', 'min/js/jquery-ui.i6tw8z.js' => '', 'min/js/jquery.all.2f248267.js' => '', 'min/js/jquery.all.d2w76v.js' => '', 'min/js/jquery.city.6b036feb.js' => '', 'min/js/jquery.city.toxdrf.js' => '', 'min/js/jquery.easydropdown.2ni3i0.js' => '', 'min/js/jquery.easydropdown.98fa138.js' => '', 'min/js/jquery.matrix.3vrqkk.js' => '', 'min/js/jquery.matrix.dfe2a44.js' => '', 'min/js/jquery.mobile.all.3539ebb7.js' => '', 'min/js/jquery.mobile.all.ernu7r.js' => '', 'min/js/jquery.qrcode.7d9738b3.js' => '', 'min/js/jquery.qrcode.yuhnsj.js' => '', 'min/js/jquery.tinyscrollbar.578e4cb8.js' => '', 'min/js/jquery.tinyscrollbar.oakk3c.js' => '', 'min/js/mobiscroll.custom.4a684f66.js' => '', 'min/js/mobiscroll.custom.kn8h2e.js' => '', 'min/js/store.536545cb.js' => '', 'min/js/store.n50jwr.js' => '', 'min/js/swiper.4650ad75.js' => '', 'min/js/swiper.animate1.0.2.517f82e8.js' => '', 'min/js/swiper.animate1.0.2.mm27zc.js' => '', 'min/js/swiper.jicwhh.js' => '', ); 点击展开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?php
 
$resState = array(
     'css/home/index.css' => 'gwy933',
     'js/echarts-all.min.js' => 'wqrf1c',
     'js/home/index.js' => 's2z6f5',
     'js/icon.js' => 'pgcyih',
     'js/icon_home.js' => 'zhl9iu',
     'js/ion.rangeSlider.min.js' => 'akq381',
     'js/jquery-ui-autocomplete.js' => '8nzacv',
     'js/jquery-ui.min.js' => 'i6tw8z',
     'js/jquery.all.min.js' => 'd2w76v',
     'js/jquery.city.js' => 'toxdrf',
     'js/jquery.easydropdown.min.js' => '2ni3i0',
     'js/jquery.matrix.js' => '3vrqkk',
     'js/jquery.mobile.all.min.js' => 'ernu7r',
     'js/jquery.qrcode.min.js' => 'yuhnsj',
     'js/jquery.tinyscrollbar.min.js' => 'oakk3c',
     'js/mobiscroll.custom.min.js' => 'kn8h2e',
     'js/store.min.js' => 'n50jwr',
     'js/swiper.animate1.0.2.min.js' => 'mm27zc',
     'js/swiper.min.js' => 'jicwhh',
     'min/css/home/index.6a4e83eb.css' => '',
     'min/css/home/index.gwy933.css' => '',
     'min/css/home/index.puzbnf.css' => '',
     'min/css/home/index.thv8x7.css' => '',
     'min/js/echarts-all.76025ee0.js' => '',
     'min/js/echarts-all.wqrf1c.js' => '',
     'min/js/home/index.65363d41.js' => '',
     'min/js/home/index.s2z6f5.js' => '',
     'min/js/icon.5bbd4db9.js' => '',
     'min/js/icon.pgcyih.js' => '',
     'min/js/icon_home.7fe74076.js' => '',
     'min/js/icon_home.zhl9iu.js' => '',
     'min/js/ion.rangeSlider.261d8ed1.js' => '',
     'min/js/ion.rangeSlider.akq381.js' => '',
     'min/js/jquery-ui-autocomplete.1f3bb62f.js' => '',
     'min/js/jquery-ui-autocomplete.8nzacv.js' => '',
     'min/js/jquery-ui.418e9683.js' => '',
     'min/js/jquery-ui.i6tw8z.js' => '',
     'min/js/jquery.all.2f248267.js' => '',
     'min/js/jquery.all.d2w76v.js' => '',
     'min/js/jquery.city.6b036feb.js' => '',
     'min/js/jquery.city.toxdrf.js' => '',
     'min/js/jquery.easydropdown.2ni3i0.js' => '',
     'min/js/jquery.easydropdown.98fa138.js' => '',
     'min/js/jquery.matrix.3vrqkk.js' => '',
     'min/js/jquery.matrix.dfe2a44.js' => '',
     'min/js/jquery.mobile.all.3539ebb7.js' => '',
     'min/js/jquery.mobile.all.ernu7r.js' => '',
     'min/js/jquery.qrcode.7d9738b3.js' => '',
     'min/js/jquery.qrcode.yuhnsj.js' => '',
     'min/js/jquery.tinyscrollbar.578e4cb8.js' => '',
     'min/js/jquery.tinyscrollbar.oakk3c.js' => '',
     'min/js/mobiscroll.custom.4a684f66.js' => '',
     'min/js/mobiscroll.custom.kn8h2e.js' => '',
     'min/js/store.536545cb.js' => '',
     'min/js/store.n50jwr.js' => '',
     'min/js/swiper.4650ad75.js' => '',
     'min/js/swiper.animate1.0.2.517f82e8.js' => '',
     'min/js/swiper.animate1.0.2.mm27zc.js' => '',
     'min/js/swiper.jicwhh.js' => '',
);
 
点击打开

 

其它附上JShrink那些PHP类的链接给大家下载 

借使我们要么以为远远不够OK的话,作者直接将这么些实验项目打包供我们下载下来学习和掌握:

四、结语

说起底自身来享受大家线上项目标现实贯彻方案:

大家的档期的顺序分线上情状、开荒条件和测验意况,在支付和测验意况中,大家每贰回访谈都会调用压缩文件的接口,然后再对转移的能源文件的大大小小是要做剖断的,要是缩减后文件过小,将要求将该能源文件的代码合併到另外能源文件里去,以此减弱不供给的HTTP央求(因为文件太小,能源的下载时间远远低于HTTP须要响应所开支的年华);另一个是图表的管理,全数图片都要透过压缩技能透过(举个例子在:  那几个网址去减少图片),在PC端,如若是小Logo的话,使用图片合併的主意开展优化,详细情形可参谋自个儿的那篇博文:http://www.cnblogs.com/it-cen/p/4618954.html    而在wap端的图片管理利用的是base64编码格局来管理图片,详细情况能够参照自己的那篇博文:  ,当页面输出时,会接纳redis来缓存页面(为什么用内部存款和储蓄器来缓存实际不是运用页面缓存,那么些现在再享受给大家)。借使是线上情况,每发一回版本,才会调用一下财富文件裁减那个接口,何况线上的静态能源(css、js、图片)是贮存在在Ali云的OSS里的,与我们的应用服务器是分开的。那是我们线上种类的一有的优化解决方案,当然了,还会有越来越多优化本事,小编会在此后各类总计和享用出去,方便大家一块儿学学和调换。

本次博文就享受到此,感激观望此博文的情大家。

1 赞 1 收藏 评论

巴黎人手机版 7

文本上传例子

class html
{
var $dir; //dir for the htmls(without/)
var $rootdir; //root of html files(without/):html
var $name; //html文件存放路线
var $dirname; //钦赐的文书夹名称
var $url; //获取html文件消息的源于网页地址
var $time; //html文件消息填加时的时日
var $dirtype; //目录寄存格局:year,month,,,,
var $nametype; //html文件命名格局:name

此处是来源于网民的二个贯彻的文件上传类代码,大家详细的牵线了每一个变量的用处,上边看看吧,有亟待能够参见一下。

<?php
/**
* 邮件类
* Enter description here ...
* @author df
* Mail::getMail()->sendMail();
*
*/
class Mail{

 代码如下

function html($nametype='name',$dirtype='year',$rootdir='html')

<?php教程
 /**
  * 文件上传类
  */
 class uploadFile {

  public $max_size = '1000000';//设置上传文件大小
  public $file_name = 'date';//重命名格局表示以时间命名,别的则运用予以的名目
  public $allow_types;//允许上传的文本扩大名,分化文件类型用“|”隔绝
  public $errmsg = '';//错误新闻
  public $uploaded = '';//上传后的公文名(包涵文件路线)
  public $save_path;//上传文件保留路径
  private $files;//提交的等候上传文件
  private $file_type = array();//文件类型
  private $ext = '';//上传文件扩大名

  /**
   * 构造函数,开首化类
   * @access public
   * @param string $file_name 上传后的文件名
   * @param string $save_path 上传的对象文件夹
   */
  public function __construct($save_path = './upload/',$file_name = 'date',$allow_types = '') {
  $this->file_name   = $file_name;//重命名方式意味着以时日命名,其余则采纳予以的称呼
  $this->save_path   = (preg_match('//$/',$save_path)) ? $save_path : $save_path . '/';
  $this->allow_types = $allow_types == '' ? 'jpg|gif|png|zip|rar' : $allow_types;
  }

  /**
   * 上传文件
   * @access public
   * @param $files 等待上传的文本(表单传来的$_FILES[])
   * @return boolean 重返布尔值
   */
 public function upload_file($files) {
  $name = $files['name'];
  $type = $files['type'];
  $size = $files['size'];
  $tmp_name = $files['tmp_name'];
  $error = $files['error'];

  switch ($error) {
   case 0 : $this->errmsg = '';
    break;
   case 1 : $this->errmsg = '抢先了php.ini汉语件大小';
    break;
   case 2 : $this->errmsg = '超过了MAX_FILE_SIZE 选项钦命的文书大小';
    break;
       case 3 : $this->errmsg = '文件唯有一部分被上传';
    break;
   case 4 : $this->errmsg = '未有公文被上传';
    break;
   case 5 : $this->errmsg = '上传文件大小为0';
    break;
      default : $this->errmsg = '上传文件退步!';
    break;
   }
  if($error == 0 && is_uploaded_file($tmp_name)) {
   //检查测量检验文件类型
   if($this->check_file_type($name) == FALSE){
    return FALSE;
   }
   //检验文件大小
   if($size > $this->max_size){
    $this->errmsg = '上传文件<font color=red>'.$name.'</font>太大,最大支撑<font color=red>'.ceil($this->max_size/1024).'</font>kb的文件';
    return FALSE;
   }
   $this->set_save_path();//设置文件贮存路线
   $new_name = $this->file_name != 'date' ? $this->file_name.'.'.$this->ext : date('YmdHis').'.'.$this->ext;//设置新文件名
   $this->uploaded = $this->save_path.$new_name;//上传后的文本名
   //移动文件
   if(move_uploaded_file($tmp_name,$this->uploaded)){
    $this->errmsg = '文件<font color=red>'.$this->uploaded.'</font>上传成功!';
    return TRUE;
   }else{
    $this->errmsg = '文件<font color=red>'.$this->uploaded.'</font>上传战败!';
    return FALSE;
   }

  }
 }

  /**
   * 检查上传文件类型
   * @access public
   * @param string $filename 等待检查的文件名
   * @return 假如检查通过重返TRUE 未经过则赶回FALSE和不当新闻
   */
    public function check_file_type($filename){
  $ext = $this->get_file_type($filename);
  $this->ext = $ext;
    $allow_types = explode('|',$this->allow_types);//分割允许上传的文本扩张名称叫数组
    //echo $ext;
    //检查上传文件扩充名是不是在请允许上传的文本扩大名中
    if(in_array($ext,$allow_types)){
     return TRUE;
    }else{
     $this->errmsg = '上传文件<font color=red>'.$filename.'</font>类型错误,只帮忙上传<font color=red>'.str_replace('|',',',$this->allow_types).'</font>等文件类型!';
     return FALSE;
    }
    }

    /**
     * 猎取文件类型
     * @access public
     * @param string $filename 要赢得文件类型的指标文件名
     * @return string 文件类型
     */
    public function get_file_type($filename){
     $info = pathinfo($filename);
     $ext = $info['extension'];
     return $ext;
    }

 /**
  * 设置文件上传后的保留路线
  */
 public function set_save_path(){
  $this->save_path = (preg_match('//$/',$this->save_path)) ? $this->save_path : $this->save_path . '/';
  if(!is_dir($this->save_path)){
   //固然目录不设有,创建目录
   $this->set_dir();
  }
 }


 /**
  * 创制目录
  * @access public
  * @param string $dir 要创制目录的不二秘籍
  * @return boolean 失利时回来错误音信和FALSE
  */
 public function set_dir($dir = null){
  //检查路线是不是存在
  if(!$dir){
   $dir = $this->save_path;
  }
  if(is_dir($dir)){
   $this->errmsg = '须求创建的公文夹已经存在!';
  }
  $dir = explode('/', $dir);
  foreach($dir as $v){
   if($v){
    $d .= $v . '/';
    if(!is_dir($d)){
     $state = mkdir($d, 0777);
     if(!$state)
      $this->errmsg = '在开立目录<font color=red>' . $d . '时出错!';
    }
   }
  }
  return true;
 }
 }

/*************************************************
 * 图片管理类
 *
 * 能够对图纸张开转换缩略图,打水印等操作
 * 本类私下认可编码为UTF8 倘诺要在GBK下使用请将img_mark方法中打粤语字符串水印iconv疏解去掉
 *
 * 由于UTF8汉字和保加利亚(Bulgaria)语字母大小(像素)倒霉确定,在中塞尔维亚共和国语混合出现太多时可能会油可是生字符串偏左
 * 或偏右,请依据项目意况对get_mark_xy方法中的$strc_w = strlen($this->mark_str)*7+5进
 * 行调整
 * 要求GD库帮衬,为越来越好使用本类推荐使用GD库2.0+
 *
 * @author kickflip@php100 QQ263340607
 *************************************************/

 class uploadImg extends uploadFile {

 public $mark_str = 'kickflip@php100';  //水印字符串
 public $str_r = 0; //字符串颜色福特Explorer
 public $str_g = 0; //字符串颜色G
 public $str_b = 0; //字符串颜色B
 public $mark_ttf = './upload/SIMSUN.TTC'; //水印文字字体文件(包含路线)
 public $mark_logo = './upload/logo.png';    //水印图片
 public $resize_h;//生成缩略图高
 public $resize_w;//生成缩略图宽
 public $source_img;//源图片文件
 public $dst_path = './upload/';//缩略图像和文字件贮存目录,不填则为源图片贮存目录

 /**
  * 生成缩略图 生成后的图
  * @access public
  * @param integer $w 收缩后图片的宽(px)
  * @param integer $h 裁减后图片的高(px)
  * @param string $source_img 源图片(路径+文件名)
  */
 public function img_resized($w,$h,$source_img = NULL){
  $source_img = $source_img == NULL ? $this->uploaded : $source_img;//获得源文件的地方,假设为空则默感觉上次上传的图纸
  if(!is_file($source_img)) { //检查源图片是不是存在
   $this->errmsg = '文件'.$source_img.'不存在';
   return FALSE;
  }
  $this->source_img = $source_img;
  $img_info = getimagesize($source_img);
  $source = $this->img_create($source_img); //创造源图片
  $this->resize_w = $w;
  $this->resize_h = $h;
  $thumb = imagecreatetruecolor($w,$h);
  imagecopyresized($thumb,$source,0,0,0,0,$w,$h,$img_info[0],$img_info[1]);//生成缩略图片
  $dst_path = $this->dst_path == '' ? $this->save_path : $this->dst_path; //获得目的文件夹路线
  $dst_path = (preg_match('//$/',$dst_path)) ? $dst_path : $dst_path . '/';//将对象文件夹后增进/
  if(!is_dir($dst_path)) $this->set_dir($dst_path); //如果不设有指标文件夹则开创
  $dst_name = $this->set_newname($source_img);
  $this->img_output($thumb,$dst_name);//输出图片
  imagedestroy($source);
  imagedestroy($thumb);
 }

 /**
  *打水印
  *@access public
  *@param string $source_img 源图片路线+文件名
  *@param integer $mark_type 水印类型(1为斯洛伐克共和国(The Slovak Republic)语字符串,2为粤语字符串,3为图片logo,默以为匈牙利(Magyarország)语字符串)
  *@param integer $mark_postion 水印地方(1为左下角,2为右下角,3为左上角,4为右上角,默以为右下角);
  *@return 打上水印的图样
  */
 public function img_mark($source_img = NULL,$mark_type = 1,$mark_postion = 2) {
  $source_img = $source_img == NULL ? $this->uploaded : $source_img;//获得源文件的地点,假设为空则默认为上次上传的图形
  if(!is_file($source_img)) { //检查源图片是还是不是留存
   $this->errmsg = '文件'.$source_img.'不存在';
   return FALSE;
  }
  $this->source_img = $source_img;
  $img_info = getimagesize($source_img);
  $source = $this->img_create($source_img); //成立源图片
  $mark_xy = $this->get_mark_xy($mark_postion);//获得水印地点
  $mark_color = imagecolorallocate($source,$this->str_r,$this->str_g,$this->str_b);

  switch($mark_type) {

   case 1 : //加匈牙利(Magyarország)语字符串水印
   $str = $this->mark_str;
   imagestring($source,5,$mark_xy[0],$mark_xy[1],$str,$mark_color);
   $this->img_output($source,$source_img);
   break;

            case 2 : //加中文字符串水印
            if(!is_file($this->mark_ttf)) { //检查字体文件是还是不是存在
    $this->errmsg = '打水印战败:字体文件'.$this->mark_ttf.'不存在!';
   return FALSE;
   }
   $str = $this->mark_str;
   //$str = iconv('gbk','utf-8',$str);//转变字符编码 借使应用GBK编码请去掉此行注释
   imagettftext($source,12,0,$mark_xy[2],$mark_xy[3],$mark_color,$this->mark_ttf,$str);
   $this->img_output($source,$source_img);
   break;

   case 3 : //加图片水印
   if(is_file($this->mark_logo)){  //假如存在水印logo的图纸则收获logo图片的着力新闻,不设有则脱离
    $logo_info = getimagesize($this->mark_logo);
   }else{
    $this->errmsg = '打水印退步:logo文件'.$this->mark_logo.'不存在!';
    return FALSE;
   }

   $logo_info = getimagesize($this->mark_logo);
   if($logo_info[0]>$img_info[0] || $logo_info[1]>$img_info[1]) { //如果源图片小于logo大小则脱离
    $this->errmsg = '打水印失利:源图片'.$this->source_img.'比'.$this->mark_logo.'小!';
    return FALSE;
   }

   $logo = $this->img_create($this->mark_logo);
   imagecopy ( $source, $logo, $mark_xy[4], $mark_xy[5], 0, 0, $logo_info[0], $logo_info[1]);
   $this->img_output($source,$source_img);
   break;

   default: //别的则为文字图片
   $str = $this->mark_str;
   imagestring($source,5,$mark_xy[0],$mark_xy[1],$str,$mark_color);
   $this->img_output($source,$source_img);
   break;
  }
  imagedestroy($source);
 }

 /**
  * 取得水印地点
  * @access private
  * @param integer $mark_postion 水印的职务(1为左下角,2为右下角,3为左上角,4为右上角,别的为右下角)
  * @return array $mark_xy 水印地点的坐标(索引0为朝鲜语字符串水印坐标X,索引1为塞尔维亚语字符串水印坐标Y,
  * 索引2为汉语字符串水印坐标X,索引3为华语字符串水印坐标Y,索引4为水印图片坐标X,索引5为水印图片坐标Y)
  */
 private function get_mark_xy($mark_postion){
  $img_info = getimagesize($this->source_img);

  $stre_w = strlen($this->mark_str)*9+5 ; //水印加泰罗尼亚语字符串的长度(px)(5号字的罗马尼亚(România)语字符大小约为9px 为了雅观再加5px)
  //(12号字的华语字符大小为12px,在utf8里三个汉字长度为3个字节一个字节4px 而二个西班牙语字符长度多个字节大小大致为9px
  // 为了在中克罗地亚语混合的景况下显得完全 设它的长度为字节数*7px)
  $strc_w = strlen($this->mark_str)*7+5 ; //水印普通话字符串的长度(px)

  if(is_file($this->mark_logo)){ //要是存在水印logo的图样则赢得logo图片的中央消息
   $logo_info = getimagesize($this->mark_logo);
  }

  //由于imagestring函数和imagettftext函数中对此字符串早先地方差异所以乌克兰语和国语字符串的Y地方也迥然区别
  //imagestring函数是从文字的左上角为参照 imagettftext函数是从文字左下角为参照
  switch($mark_postion){

   case 1: //地方左下角
   $mark_xy[0] = 5; //水印乌Crane语字符串坐标X
   $mark_xy[1] = $img_info[1]-20;//水印俄语字符串坐标Y
   $mark_xy[2] = 5; //水印中文字符串坐标X
   $mark_xy[3] = $img_info[1]-5;//水印汉语字符串坐标Y
   $mark_xy[4] = 5;//水印图片坐标X
   $mark_xy[5] = $img_info[1]-$logo_info[1]-5;//水印图片坐标Y
   break;

   case 2: //地方右下角
   $mark_xy[0] = $img_info[0]-$stre_w; //水印塞尔维亚(Serbia)语字符串坐标X
   $mark_xy[1] = $img_info[1]-20;//水印丹麦语字符串坐标Y
   $mark_xy[2] = $img_info[0]-$strc_w; //水印汉语字符串坐标X
   $mark_xy[3] = $img_info[1]-5;//水印汉语字符串坐标Y
   $mark_xy[4] = $img_info[0]-$logo_info[0]-5;//水印图片坐标X
   $mark_xy[5] = $img_info[1]-$logo_info[1]-5;//水印图片坐标Y
   break;

   case 3: //地点左上角
   $mark_xy[0] = 5; //水印葡萄牙语字符串坐标X
   $mark_xy[1] = 5;//水印土耳其共和国语字符串坐标Y
   $mark_xy[2] = 5; //水印中文字符串坐标X
   $mark_xy[3] = 15;//水印中文字符串坐标Y
   $mark_xy[4] = 5;//水印图片坐标X
   $mark_xy[5] = 5;//水印图片坐标Y
   break;

   case 4: //地方右上角
   $mark_xy[0] = $img_info[0]-$stre_w; //水印英语字符串坐标X
   $mark_xy[1] = 5;//水印保加巴塞尔语字符串坐标Y
   $mark_xy[2] = $img_info[0]-$strc_w; //水印普通话字符串坐标X
   $mark_xy[3] = 15;//水印粤语字符串坐标Y
   $mark_xy[4] = $img_info[0]-$logo_info[0]-5;//水印图片坐标X
   $mark_xy[5] = 5;//水印图片坐标Y
   break;

   default : //其它暗中同意为右下角
   $mark_xy[0] = $img_info[0]-$stre_w; //水印瑞典语字符串坐标X
   $mark_xy[1] = $img_info[1]-5;//水印匈牙利语字符串坐标Y
   $mark_xy[2] = $img_info[0]-$strc_w; //水印普通话字符串坐标X
   $mark_xy[3] = $img_info[1]-15;//水印普通话字符串坐标Y
   $mark_xy[4] = $img_info[0]-$logo_info[0]-5;//水印图片坐标X
   $mark_xy[5] = $img_info[1]-$logo_info[1]-5;//水印图片坐标Y
   break;
  }
  return $mark_xy;
 }

 /**
  * 制造源图片
  * @access private
  * @param string $source_img 源图片(路径+文件名)
  * @return img 从目的文件新建的图像
  */
 private function img_create($source_img) {
  $info = getimagesize($source_img);
  switch ($info[2]){
            case 1:
            if(!function_exists('imagecreatefromgif')){
             $source = @imagecreatefromjpeg($source_img);
            }else{
             $source = @imagecreatefromgif($source_img);
            }
            break;
            case 2:
            $source = @imagecreatefromjpeg($source_img);
            break;
            case 3:
            $source = @imagecreatefrompng($source_img);
            break;
            case 6:
            $source = @imagecreatefromwbmp($source_img);
            break;
            default:
   $source = FALSE;
   break;
        }
  return $source;
 }

 /**
  * 重命名图片
  * @access private
  * @param string $source_img 源图片路线+文件名
  * @return string $dst_name 重命名后的图纸名(路线+文件名)
  */
 private function set_newname($sourse_img) {
  $info = pathinfo($sourse_img);
  $new_name = $this->resize_w.'_'.$this->resize_h.'_'.$info['basename'];//将文件名修改为:宽_高_文件名
  if($this->dst_path == ''){ //假设寄放缩略图路线为空则默感到源文件同文件夹
   $dst_name = str_replace($info['basename'],$new_name,$sourse_img);
  }else{
   $dst_name = $this->dst_path.$new_name;
  }
  return $dst_name;
 }

 /**
  * 输出图片
  * @access private
  * @param $im 管理后的图样
  * @param $dst_name 输出后的的图纸名(路线+文件名)
  * @return 输出图片
  */
 public function img_output($im,$dst_name) {
  $info = getimagesize($this->source_img);
  switch ($info[2]){
            case 1:
            if(!function_exists('imagegif')){
             imagejpeg($im,$dst_name);
            }else{
             imagegif($im, $dst_name);
            }
            break;
            case 2:
            imagejpeg($im,$dst_name);
            break;
            case 3:
            imagepng($im,$dst_name);
            break;
            case 6:
            imagewbmp($im,$dst_name);
            break;
        }
 }

 }
?>

private static $__mail=null;//邮箱类对象
private $__PMAIL=NULL;
function __construct(){
require('class.phpmailer.php');
$this->__PMAIL=new PHPMailer();
$this->__PMAIL->IsSMTP();
$this->__PMAIL->Host= "smtp.163.com";
$this->__PMAIL->Username="";
$this->__PMAIL->Password="";
$this->__PMAIL->SMTPAuth=true;
$this->__PMAIL->From="";
}
public static function getMail(){
/*if(!self::$__mail){
self::$__mail=new Mail();
}
return self::$__mail;
*/
return new Mail();
}
/**
*
* Enter description here ...
* @param unknown_type $toAddress //收件人地址,八个可用,好分隔
* @param unknown_type $fromName //发件人名字
* @param unknown_type $title //标题
* @param unknown_type $content //内容
* @param unknown_type $isHTML //是或不是以HTML格式发送
* @param unknown_type $charset //编码
* @param unknown_type $replyto //收件人地址
* @param unknown_type $attachment //附件
*/
function sendMail($toAddress,$title='',$content='',$isHTML=TRUE,$charset='utf-8',$replyto='',$fromName='',$attachment=''){
$this->__PMAIL->IsHTML($isHTML);
$this->__PMAIL->CharSet=$charset;
if(strstr($toAddress,',')){
$__list=explode(',', $toAddress);
foreach ($__list as $v){
$this->__PMAIL->AddAddress($v,$v);
}
}else{
$this->__PMAIL->AddAddress($toAddress,$toAddress);
}

<?php
header('content-type:text/html;charset=utf-8');
require('uploadFile.php');

function setvar($nametype='name',$dirtype='year',$rootdir='html')

本条写成了上传文件类就有益多了,把上边代码保存三个文书它就足以共用调用与修改删除了。

$this->__PMAIL->FromName=$fromName;
$this->__PMAIL->Subject=$title;
$this->__PMAIL->Body=$content;
if($replyto){
$this->__PMAIL->AddReplyTo($replyto);
}
if($attachment){
$this->__PMAIL->AddAttachment($attachment,$attachment);
}
return $this->__PMAIL->Send();
}
}

if(isset($_POST['submit'])){
$uploads = $_FILES['file'];
$num_file = count($uploads['name']);

function createdir($dir='')
{
$this->dir=$dir?$dir:$this->dir;

$up = new UploadFile($uploads,'uploads',1024);
$num = $up->upload();

if (!is_dir($this->dir))
{
$temp = explode('/',$this->dir);
$cur_dir = '';
for($i=0;$i {
$cur_dir .= $temp[$i].'/';
if (!is_dir($cur_dir))

if($num == $num_file ){
echo '全体文本上传成功';
exit;
}else{
echo $num,'个文件上传成功<br/>';
echo $up->showErrorInfo();
exit;
}
}

}
}
}

?>

function getdir($dirname='',$time=0)
{
$this->time=$time?$time:$this->time;
$this->dirname=$dirname?$dirname:$this->dirname;

本文由巴黎人手机版发布于巴黎人-前端,转载请注明出处:把上面代码保存一个文件它就可以公共调用与修

上一篇:原文出处,巴黎人手机版workers标准让在Web App上拥 下一篇:没有了
猜你喜欢
热门排行
精彩图文