经过前几节的学习,读者应该对文件上传下载的逻辑过程和技术实现有了基本的认识。本节将完成已上传文件的列表展示功能和对应文件的下载。文件下载部分程序由两部分构成,即文件列表页面(list.php)和文件下载程序(download.php)组成。
1. 文件下载列表
文件下载页面用来将已经上传的文件以列表的方式直观地展示出来,方便下载者了解所下载文件的基本信息。下面设计一个基本的下载页面,核心框架部分代码如下:
<HEAD> <TITLE>文件下载列表</TITLE> <META http-equiv=Content-Type content="text/html; charset=utf-8"> <LINK href="base.css" type=text/css rel=stylesheet> <BODY> <DIV class=bodytitle> <DIV class=bodytitleleft></DIV> <DIV class=bodytitletxt>文件下载列表</DIV></DIV> <TABLE class=tbtitle style="MARGIN-TOP: 6px; BACKGROUND: #e2f5bc" height=31 cellSpacing=1 cellPadding=1 width="96%" align=center border=0> <TBODY> <TR> <TD class=tbtitletxt><STRONG> 请选需要下载的文件:</STRONG></TD> </TR> </TBODY> </TABLE> <TABLE class=tblist style="BORDER-RIGHT: #e2f5bc 1px solid; BORDER-TOP: #e2f5bc 1px solid; MARGIN: 0px 0px 6px; BORDER-LEFT: #e2f5bc 1px solid; BORDER-BOTTOM: #e2f5bc 1px solid" cellSpacing=1 cellPadding=1 width="96%" align=center border=0> <TBODY> <TR align=middle> <TD class=tbsname style="PADDING-RIGHT: 6px; PADDING-LEFT: 6px; PADDING-BOTTOM: 20px; PADDING-TOP: 6px" vAlign=top align=left height=120> <TABLE cellSpacing=0 cellPadding=6 width="90%" border=0> <TBODY> <TR> <TD> <STRONG>下载说明:</STRONG><BR> 1、选择需要下载的文件后在‘操作选项’中选择‘文件下载’选项; </TD> </TR> </TBODY> </TABLE> <TABLE cellSpacing=1 cellPadding=3 width="98%" bgColor=#cae886 border=0> <TBODY> <TR align=middle height=20> <TD width="8%" bgColor=#dcf4bd><STRONG>ID</STRONG></TD> <TD width="17%" bgColor=#dcf4bd><STRONG>文件名</STRONG></TD> <TD width="11%" bgColor=#dcf4bd><strong>文件尺寸</strong></TD> <TD width="18%" bgColor=#dcf4bd><strong>文件类型</strong></TD> <TD width="18%" bgColor=#dcf4bd><strong>上传时间</strong></TD> <TD width="28%" bgColor=#dcf4bd><STRONG>操作选项</STRONG></TD> </TR> <TR onmousemove="javascript:this.bgColor='#FCFDEE';" onmouseout="javascript:this.bgColor='#FFFFFF';" align=middle bgColor=#ffffff height=20> <TD>1</TD> <TD>图书目录.doc</TD> <TD>10kb</TD> <TD>.doc</TD> <TD>0</TD> <TD> <A href="download.php">文件下载</A> | <FONT color=#cccccc>扩展功能1</FONT> | <FONT color=#cccccc>扩展功能2</FONT> </TD> </TR> </TBODY> </TABLE> <TABLE cellSpacing=0 cellPadding=0 width="90%" border=0></TABLE> </TD> </TR> </TBODY> </TABLE> </BODY> </HTML>
接下来在数据库中将已经下载的文件提取出来,再嵌套到HTML页面中。经过前面的学习,这段代码读者应该很容易写出来,展示部分的核心代码(页面模板部分代码请读者参考源程序)如下:
<TBODY> <TR align=middle height=20> <TD width="8%" bgColor=#dcf4bd><STRONG>ID</STRONG></TD> <TD width="17%" bgColor=#dcf4bd><STRONG>文件名</STRONG></TD> <TD width="11%" bgColor=#dcf4bd><strong>文件尺寸</strong></TD> <TD width="18%" bgColor=#dcf4bd><strong>文件类型</strong></TD> <TD width="18%" bgColor=#dcf4bd><strong>上传时间</strong></TD> <TD width="28%" bgColor=#dcf4bd><STRONG>操作选项</STRONG></TD> </TR> <?php $con = mysqli_connect('localhost', 'root', 'root') or die('Could not connect: ' . mysqli_error()); //echo 'Connected successfully'; $db=mysqli_select_db($con,'download'); if (!$db){ die ("Can\'t use download : " . mysqli_error()); }else{ $sql = "SELECT * FROM `f_detail`"; $result = mysqli_query($con,$sql); $err = mysqli_error(); if($err){ echo "发生错误,请联系管理员"; } while ($row = mysqli_fetch_array($result, MYSQL_NUM)) { //var_dump ($row); ?> <!--循环start--> <TR align=middle bgColor=#ffffff height=20> <TD><?php echo $row[0]?></TD> <TD><?php echo $row[1]?></TD> <TD><?php echo $row[3]?></TD> <TD><?php echo $row[4]?></TD> <TD><?php echo $row[5]?></TD> <TD> <A href="download.php?id=<?php echo $row[0]?>">文件下载</A> | <FONT color=#cccccc>扩展功能1</FONT> | <FONT color=#cccccc>扩展功能2</FONT> </TD> </TR> <!--循环end--> <?php } mysqli_free_result($result); } ?> </TBODY>
【代码解读】
在上述代码中,将数据中的文件上传信息读取出来放入数组中,然后在通过while)函数循环遍历出来,再将输出的内容嵌入页面代码模板中。
运行list.php文件,执行结果如图7.3所示。从图中可以看到,程序已经正确地显示了文件列表和相应的下载链接。
图1.1文件下载列表页面
2. 文件下载程序实现
打开download.php文件,该文件是负责处理文件下载逻辑的。但是它不完善,现在要根据“文件下载列表页面”中“文件下载”选项提供的链接形式接收参数。
注意:在使用 header()函数发送原始HTTP标头时,该文件不能有任何字符的输出,否则将影响浏览器识别导致下载失败。
该文件的具体的代码如下:
<? // 创建数据库连接 $con = mysqli_connect('localhost', 'root', 'root') or die('Could not connect: ' . mysqli_error()); //echo 'Connected successfully'; $db=mysqli_select_db($con,'download'); if (!$db){ die ("Can\'t use download : " . mysqli_error()); }else{ // 将用户信息插入数据库的user表 $sql = "SELECT * FROM `f_detail` WHERE `id` ='".$_GET['id']."' LIMIT 0 , 30"; $result = mysqli_query($con,$sql); $row=mysqli_fetch_row($result); if (!$result){ // 释放结果集 mysqli_free_result($result); // 关闭连接 mysqli_close($db); echo '数据记录插入失败!'; exit; } } //下载文件名 //$file_name = "xxx.rar"; $file_name = $row[1]; //var_dump($file_name); //下载文件存放目录 $file_dir = "up/"; //检查文件是否存在 if(!file_exists($file_dir . $file_name)){ echo "文件找不到"; exit; }else{ // 打开文件 $file = fopen($file_dir . $file_name,"r"); // 输入文件标签 Header("Content-type: application/octet-stream"); Header("Accept-Ranges: bytes"); Header("Accept-Length: ".filesize($file_dir . $file_name)); Header("Content-Disposition: attachment; filename=" . $file_name); // 输出文件内容 //读取文件内容并直接输出到浏览器 echo fread($file,filesize($file_dir . $file_name)); fclose($file); exit; } ?>
执行download.php这个文件,给定id参数为3,根据数据库中对应的数据值可知道,该程序将提示下载名称为1264272773.doc的文件。执行文件效果如图7.4所示。
图2.1下载提示页面
至此,文件上传和下载的程序实现就全部完成了。通过前面的验证可以知道,程序达到了预先期望的文件归档和安全下载的目的。
3 小 结
本章的重点是介绍PHP实现文件上传和下载的基本原理。文件上传与下载是网站的常用功能,它对数据的可靠性和安全性都有一定的要求。第1节讲解了文件上传与下载的原理。第2节介绍了文件尺寸限制及异常处理等,具体内容是客户端的验证解决方案(JavaScript文件尺寸验证)和服务端的验证解决方案(PHP上传文件涉及的参数)。在实现了文件的上传和下载之后,通过数据库对上传的文件进行归档和管理。本节对整个上传和下载做了流程上的梳理,最终构成了完整的文件上传和下载的模块应用,并在这个过程中将遇到的技术难点做了详细的讲解。