2.7 简单公开文件服务器中的文档
在各种企业内部文档管理系统中都有公开文档的要求,一般的做法是将那些需要公开的文档的URL(或曰链接)放在一个静态的HTML上,再每天适时更新这个HTML文件。这样的做法不仅费时费力,而且维护起来也很麻烦,不能做到真正的及时公开。本节应用PHP技术实现真正及时地公开文档。
在特定文件夹下的文档自动显示在HTML页面中,再也不用每天去费力手动修改HTML了,而且这些自动处理能保证公开文档的绝对正确性和适时性。
本例要点
在理解本节应用的逻辑之前,请先看看如下两点的说明。
关于递归调用
文件管理系统中文件夹都是多层的,一般的文件遍历的操作是:先遍历母文件夹中的所有文件后,再遍历母文件夹的所有子文件夹,在遍历子文件夹时,其实在文件夹中进行的是与在母文件夹中的相同动作,直到遍历完母文件夹及其子目录下的全部文件为止。这样,将母文件夹文件遍历的动作函数化,在遍历其子文件夹时再调用函数本身,这就是递归调用。本节的代码中就用到了递归调用。
正确的代码读解法
解读复杂的程序逻辑时,最开始不要先注意细节部分,而是先试着将整体的程序划分成几个相对独立的功能块,再去理解它。
针对本节的应用,即下面的index.php脚本来说,从第1行到28行为一个相对独立的功能块,完成锁定特定文件夹的功能。从43行到54行是另一功能块,完成显示文件夹信息的工作,最后56行到67行完成文件信息的显示。
这样,再逐步深入到细节部分,你就可以理解程序的全部了。
目录结构
本例代码
将函数集合脚本common.php包含进来,后面将用到这些函数。
取得显示对象目录。文件夹间移动时,系统将目录的值保存隐藏框中。首先用isset判定目录值是否被设定,如果没有设定的情况下,默认为文档根目录(./doc)。如果设定,直接保存在$current变量中。同时求出其上一级,将结果放在隐藏框dir中,作为跳转到上一级目录时的参数。
isValid函数是在common.php中定义的对对象目录进行检查的函数(是否是实际存在的目录,且为./doc下的目录)。如果是非法的目录,则中止处理。
生成对象目录的对象(object)。
Pathinfo函数取得由子目录、文件组成的数组。
如果设定值时目录时,输出“目录”的文字,以及指向index.php的连接。同时将子目录的值保存在隐藏框中。
如果是文件的情况下,输出指向disp.php的链接、后缀名、文件大小,同时在隐藏框dir中保存文件名,作为向disp.php传入的参数。
另外,还有将文件后缀名以大写字母表示,文件大小转换为千字节单位的处理。
关闭打开的文件夹。
包含common.php,应用isValid函数检测传递过来的隐藏域dir的值的合法性,dir值不合法时,处理中断。
为了将隐藏域dir所代表的文件以二进制数据的形式下载下来,必须将Content-Type头信息设置为“application/octet-stream”,这样页面将会出现下载对话框。
Content-Disposition头信息用来明确定义下载文件名,filename中设定的就是下载文件名。
fopen函数如果打开的文件如果是二进制数据时,必须在第二参数中加上[b],[r]表示以只读的形式打开文件。
fread函数是对指定的文件,读取出第二参数指定的长度(字节),filesize函数就是用来取得文件长度的。因为第二参数指定的长度就是文件本来的长度,因此,fread函数最后将整个文件读出来了。
定义固定值ROOT,为文件夹的根目录。
函数c,r将文字码在GB2312与UTF-8之间转换。
下面定义检查指定路径的合法性的函数isValid。isValid函数中,将$path与ROOT的路径转化为绝对路径。realpath函数除了转化路径中的“././”、“../../”等相对路径,也同时对文件的存在进行检查。
strncmp函数对$path路径的根目录部分与固定值根目录ROOT进行比较,mb_strlen函数求得$root的字符长度,做为函数strncmp的第三参数,限定比较的字符长度(从第一个开始)。
补充
disp.php的作用
在本节的应用中,没有disp.php这个页面,只在index.php有了各个文件的链接,就可以实现下载文件的功能。确实,disp.php只是读入对象文件,再将文件输出到页面上。这些事交给浏览器就可实现了。
但是,可以这样试试,并不是最好的方法。在页面中直接放入链接的情况下,浏览器中的文件对象就直接显示在当前浏览器中。当然在浏览器中,你可以选择“对象另存为”将文件下载下来。显然不是很方便了。而有了disp.php脚本,不仅实现了将文件显示在一个新开的窗口,也可自动下载文件了。
其他,有了这个显示用脚本做中介,可以很轻松地实现用户权限的控制。
MIME类型
MIME(Multipurpose Internet Mail Extention)是RFC822推荐的二进制数据的送受信的规格,或者说是数据的类型。例如,在浏览器上显示的HTML文件时,如果没有文件后缀名与MIME类型的关联,还有启动与MIME类型相对应的程序,就不能正确显示。
在PHP中,应用header函数定义MIME类型,当然不用定义MIME类型,浏览器也会默认将文件以HTML形式显示,如果是其他类型的文件,你必须定义MIME类型,浏览器才能正确识别。
表2-5所示的是所有MIME类型。
表2-5 MIME类型一览
知识专栏:性能调试的小技巧(一)——服务器端处理与客户端处理的分割
要提高系统的性能,首先要考虑的是进行合理的服务器端处理与客户端处理的分割。下面列举了分别适合服务器端处理与客户端处理的情况。
适合客户端处理的部分
● 针对用户输入数据的一次性检查(先于服务器端检查)。
● 用户界面的部分操作。
● 处理的数据量比较小的处理。
适合服务器端处理的部分
● 针对用户输入数据的最终检查。
● 应用程序的逻辑部分。
● 处理的数据量较大的处理。
上述的例子并不是一概而论,可作为一般性的参考。特别提醒进行初次开发的入门者,有很多往往不能很好地理解客户端与服务器端的差别。请务必注意。
共有条评论 网友评论