php文件的上传与下载其实不难的,就那么的几行代码,比起JSP的要简单得多,具体可以参考:《【Servlet】利用Servlet3.0标准与JSTL表达式实现文件上传系统,支持图片上传后显示》(点击打开链接);《【Jsp】把Java写到Respond输出流里面供用户下载》(点击打开链接);《【Struts2】文件的上传与上传权限的控制》(点击打开链接);《【Struts2】中文文件的下载与下载权限的控制》(点击打开链接),但是网上的资料众说纷纭,还用来许许多多奇怪的函数,必须整理一下。
一、基本目标
设置一个文件上传系统,指定只能上传少于1M的图片,上传之后提供此文件的下载。
同时注意好本上传下载系统的防范工作,直接输入网址访问两个处理页是不行的。这里用到了《【php】使用重定向,伪装表单处理页面不存在》(点击打开链接)重定向的思想。
当然,自然能够在上传文件夹找到这张被改名的图片,服务器上的图片一般不存中文的,改名成时间戳,后附上用户信息等。
二、基本准备
1、设置上传与下载的系统之前,先打开php目录下的php.ini,如果通过《【php】本地开发环境的部署与helloworld》(点击打开链接)一键在windows安装php,则打开..\php-5.2.14-win32下的php.ini-dist:
2、利用Ctrl+F查询按钮找到File Uploads那行,把file_uploads参数设置为On,随便给一个临时上传文件夹给php,然后设置php最大上传大小,当然,我们不是每次上传都给这个最大限度给用户,这个大小,只是像《【Struts2】文件的上传与上传权限的控制》(点击打开链接)中抛出异常的大小。
3、在工程文件夹下新建一个upload文件夹去存放上传的图片,php找不到这个文件夹则拒绝上传,当然,你可以自己写代码新建。其基本目录结构如下所示,upload.html是文件表单页,upload.php则是上传处理页,download.php则是下载处理页。
三、制作过程
1、upload.html是文件表单页,没什么好说的,就一个表单:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>文件上传</title> </head> <body> <form action="upload.php" method="post" enctype="multipart/form-data"> <input type="file" name="file" /> <input type="submit" name="submit" value="提交" /> </form> </body> </html>2、上传处理页upload.php,关键一个$_FILES["xx"],其中xx而是upload.html中的文件域的name属性,还有如何保存上传文件的问题,保存上传文件,必须利用$basepath=str_replace('\\','/',realpath(dirname(__FILE__).'/'))."/";取得服务器的绝对路径,整个思想与JSP中《【Servlet】利用Servlet3.0标准与JSTL表达式实现文件上传系统,支持图片上传后显示》( 点击打开链接)是完全类似的,具体如下:
<?php //看是否是通过正常途径传递一个file过来了 if(empty($_FILES["file"])){ //如果不是,则非正常打开此页 header("location: error.php"); exit; } else{ header("Content-type: text/html; charset=utf-8"); } //这是判断是否上传的file $canUpload=true; //这样就能够取得上传的文件名 $fileName=$_FILES["file"]["name"]; //通过对$fileName的处理,就能够取得上传的文件的后缀名 $fileExtensions=strrchr($fileName, '.'); //这样就能够取得上传文件的大小 $fileSize=$_FILES["file"]["size"]; //即将被打印的错误信息 $errmsg=""; //这里是文件的异常,一般不会出现 if($_FILES["file"]["error"]>0){ $errmsg .= "异常:".$_FILES["file"]["error"]."!"; $canUpload=false; } //如果上传的文件名的后缀不是以下的几种则不能上传 if($fileExtensions!=".bmp" && $fileExtensions!=".gif" && $fileExtensions!=".jpg" && $fileExtensions!=".jpeg" && $fileExtensions!=".png"){ $errmsg .= "只能上传图片类型!后缀名必须为:.bmp,gif,jpg,jpeg,png任一!"; $canUpload=false; } //如果上传的文件大于1M则也不能上传 if($fileSize>1*1024*1024){ $errmsg .= "文件太大!请少于1M!"; $canUpload=false; } //如果文件可以上传 if($canUpload==true){ //保存在服务器的名字则是时间戳,加文件后缀名 $saveName=time().$fileExtensions; //取得服务器的目录的绝对路径。 $basepath=str_replace('\\','/',realpath(dirname(__FILE__).'/'))."/"; //然后则保存这个上传文件 move_uploaded_file($_FILES["file"]["tmp_name"],$basepath."/upload/".$saveName); echo $fileName.",上传成功!大小:".($fileSize/1024)."KB"; //把保存在服务器的名字传到下载页,供其处理 echo "<a href='download.php?saveName=$saveName'>下载</a>"; } else{ echo $errmsg."<a href='upload.html'>返回</a>"; } ?>3、下载处理页download.php,这一页其实不写,可以正常显示图片的,但是通过把对象抛到respond对象中给用户下载,则可以提出一个下载提示框。整个思想还是与《【Jsp】把Java写到Respond输出流里面供用户下载》( 点击打开链接)一样,只是写作语言不同而已。
<?php //防止输入网址直接访问 if(empty($_REQUEST["saveName"])){ header("location: error.php"); exit; } else{ header("Content-type: text/html; charset=utf-8"); } //取得保存在服务器的名字 $fileName=$_REQUEST["saveName"]; //取得服务器的绝对路径 $basepath=str_replace('\\','/',realpath(dirname(__FILE__).'/'))."/"; $filepath=$basepath."upload/".$fileName; //读取这个文件夹,构造下载流 $fp=fopen($filepath,"r"); //返回文件给Respond对象,给用户下载 header("Content-type: application/octet-stream"); //取出文件大小,还是用于构造Respond对象 $filesize=filesize($filepath); header("Accept-Length: ".$filesize); //按照字节格式返回 header("Accept-Ranges: bytes"); //弹出客户端对话框,对应的文件名 header("Content-Disposition: attachment; filename=".$fileName); //这样就不会有文件分段,导致文件下载之后损坏的问题的 $buffer=1024; while(!feof($fp)){ $file_data=fread($fp,$buffer); echo $file_data; } //关闭文件 fclose($fp); ?>