php实现文件下载功能总结
php实现文件下载功能总结
其实所谓的下载按钮根本就是个A标签,里面记录着要下载文件的路径,如果要下载的文件恰巧是图片或者是文本文件,那么下载的时候就会被浏览器弹出一个新窗口或者直接页面跳转掉并且直接打开这个文件,解决方法是将下载的文件改成压缩后的格式或者是浏览器不能直接打开的格式。
下面我来说一下下载的流程:浏览器发送一个请求,请求访问服务器中的某个网页(如:down.php),服务器接受到该请求以后,马上运行该down.php文件,运行该文件的时候,必然要把将要被下载的文件读入内存当中,这里通过fopen()函数完成该动作,现在文件已经在内存当中了,这是需要从内存当中读取文件,通过fread()函数完成该动作需要注意的是,如果文件较大,文件应该是被分成多段返回给客户端的,并不是等文件在服务端全部读取完毕后,一次性返回给客户端,因为这样子会增加服务器的负荷。所以我们需要php代码中设置一次读取的字节数,比如我在下面的代码中通过$buffer=1024设置一次读取的字节数,每读取一次,就输出数据。
header("Content-type:text/html;charset=utf-8")的作用:在服务器响应浏览器的请求时,告诉浏览器以编码格式为UTF-8的编码显示该内容,关于file_exists()函数不支持中文路径的问题:因为php函数比较早,不支持中文,所以如果被下载的文件名是中文的话,需要对其进行字符编码转换,否则file_exists()函数不能识别,可以使用iconv()函数进行编码转换。$file_sub_path() 我使用的是绝对路径,执行效率要比相对路径高,Header("Content-type: application/octet-stream")的作用:通过这句代码客户端浏览器就能知道服务端返回的文件形式。Header("Accept-Ranges: bytes")的作用:告诉客户端浏览器返回的文件大小是按照字节进行计算的。Header("Accept-Length:".$file_size)的作用:告诉浏览器返回的文件大小。Header("Content-Disposition: attachment; filename=".$file_name)的作用:告诉浏览器返回的文件的名称。fclose($fp)可以把缓冲区内最后剩余的数据输出到磁盘文件中,并释放文件指针和有关的缓冲区。这些就是下载时候的整个流程和必要的代码。下面附上整理的下载方法,已封装好,可直接使用:
代码如下:
1 <?php 2 //文件下载,下载一张图片 3 //$file_name="Angel.mp3"; 4 $file_name="bjnihao.jpg"; //出现中文 程序无法完成下载 提示:文件不存在 5 //对文件进行转码(PHP文件函数 比较古老 需对中文码转成 gb2312) 6 //iconv — Convert string to requested character encoding 7 //by www.jb51.net 8 $file_name=iconv("utf-8","gb2312",$file_name); 9 //设置文件下载路径(相对路径) 10 //$file_path="./dowm/".$file_name; 11 //使用绝对路径 12 $file_path=$_SERVER['DOCUMENT_ROOT']."/http/dowm/".$file_name; 13 //打开文件---先判断再操作 14 if(!file_exists($file_path)){ 15 16 echo "文件不存在"; 17 return ; //直接退出 18 } 19 //存在--打开文件 20 $fp=fopen($file_path,"r"); 21 22 //获取文件大小 23 $file_size=filesize($file_path); 24 //http 下载需要的响应头 25 header("Content-type: application/octet-stream"); //返回的文件 26 header("Accept-Ranges: bytes"); //按照字节大小返回 27 header("Accept-Length: $file_size"); //返回文件大小 28 header("Content-Disposition: attachment; filename=".$file_name);//这里客户端的弹出对话框,对应的文件名 29 //向客户端返回数据 30 //设置大小输出 31 $buffer=1024; 32 //为了下载安全,我们最好做一个文件字节读取计数器 33 $file_count=0; 34 //判断文件指针是否到了文件结束的位置(读取文件是否结束) 35 while(!feof($fp) && ($file_size-$file_count)>0){ 36 $file_data=fread($fp,$buffer); 37 //统计读取多少个字节数 38 $file_count+=$buffer; 39 //把部分数据返回给浏览器 40 echo $file_data; 41 } 42 //关闭文件 43 fclose($fp); 44 ?>
封装函数:
1 <?php 2 /* 3 封装函数: 4 参数说明----$file_name:文件名 5 $file_sub_dir:文件下载的子路径 6 */ 7 function file_dowm($file_name,$file_sub_dir){ 8 //文件转码 9 $file_name=iconv("utf-8","gb2312",$file_name); 10 //使用绝对路径 11 $file_path=$_SERVER['DOCUMENT_ROOT']."$file_sub_dir".$file_name; 12 //打开文件---先判断再操作 13 if(!file_exists($file_path)){ 14 15 echo "文件不存在"; 16 return ; //直接退出 17 } 18 //存在--打开文件 19 $fp=fopen($file_path,"r"); 20 21 //获取文件大小 22 $file_size=filesize($file_path); 23 /* 24 //这里可以设置超过多大不能下载 25 if($file_size>50){ 26 echo "文件太大不能下载"; 27 return ; 28 }*/ 29 //http 下载需要的响应头 30 header("Content-type: application/octet-stream"); //返回的文件 31 header("Accept-Ranges: bytes"); //按照字节大小返回 32 header("Accept-Length: $file_size"); //返回文件大小 33 header("Content-Disposition: attachment; filename=".$file_name);//这里客户端的弹出对话框,对应的文件名 34 //向客户端返回数据 35 //设置大小输出 36 $buffer=1024; 37 //为了下载安全,我们最好做一个文件字节读取计数器 38 $file_count=0; 39 //判断文件指针是否到了文件结束的位置(读取文件是否结束) 40 while(!feof($fp) && ($file_size-$file_count)>0){ 41 $file_data=fread($fp,$buffer); 42 //统计读取多少个字节数 43 $file_count+=$buffer; 44 //把部分数据返回给浏览器 45 echo $file_data; 46 } 47 //关闭文件 48 fclose($fp); 49 } 50 51 file_dowm("bjnihao.jpg","/http/dowm/"); 52 ?>
另一个代码:
1 public function downloads($name){ 2 $name_tmp = explode("_",$name); 3 $type = $name_tmp[0]; 4 $file_time = explode(".",$name_tmp[3]); 5 $file_time = $file_time[0]; 6 $file_date = date("Y/md",$file_time); 7 $file_dir = SITE_PATH."/data/uploads/$type/$file_date/"; 8 9 if (!file_exists($file_dir.$name)){ 10 header("Content-type: text/html; charset=utf-8"); 11 echo "File not found!"; 12 exit; 13 } else { 14 $file = fopen($file_dir.$name,"r"); 15 Header("Content-type: application/octet-stream"); 16 Header("Accept-Ranges: bytes"); 17 Header("Accept-Length: ".filesize($file_dir . $name)); 18 Header("Content-Disposition: attachment; filename=".$name); 19 echo fread($file, filesize($file_dir.$name)); 20 fclose($file); 21 } 22 }
文件下载 出现下载文件内容乱码损坏的解决方法:
1 ob_clean(); 2 flush();