Php中文件下载功能实现超详细流程分析


Posted in PHP onJune 13, 2012

客户端从服务端下载文件的流程分析:

浏览器发送一个请求,请求访问服务器中的某个网页(如:down.php),该网页的代码如下。
服务器接受到该请求以后,马上运行该down.php文件
运行该文件的时候,必然要把将要被下载的文件读入内存当中(这里是圣诞狂欢.jpg这张图片),这里通过fopen()函数完成该动作
注意:任何有关从服务器下载的文件操作,必然需要先在服务端将文件读入内存当中

现在文件已经在内存当中了,这是需要从内存当中读取文件,通过fread()函数完成该动作
需要注意的是,如果文件较大,文件应该是被分成多段返回给客户端的,并不是等文件在服务端全部读取完毕后,一次性返回给客户端,因为这样子会增加服务器的负荷。
所以我们需要在php代码中设置一次读取的字节数,比如我在下面的代码中通过$buffer=1024设置一次读取的字节数,每读取一次,就输出数据(即返回给浏览器)

流程图:
Php中文件下载功能实现超详细流程分析

<?php 
header("Content-type:text/html;charset=utf-8"); 
// $file_name="cookie.jpg"; 
$file_name="圣诞狂欢.jpg"; 
//用以解决中文不能显示出来的问题 
$file_name=iconv("utf-8","gb2312",$file_name); 
$file_sub_path=$_SERVER['DOCUMENT_ROOT']."marcofly/phpstudy/down/down/"; 
$file_path=$file_sub_path.$file_name; 
//首先要判断给定的文件存在与否 
if(!file_exists($file_path)){ 
echo "没有该文件文件"; 
return ; 
} 
$fp=fopen($file_path,"r"); 
$file_size=filesize($file_path); 
//下载文件需要用到的头 
Header("Content-type: application/octet-stream"); 
Header("Accept-Ranges: bytes"); 
Header("Accept-Length:".$file_size); 
Header("Content-Disposition: attachment; filename=".$file_name); 
$buffer=1024; 
$file_count=0; 
//向浏览器返回数据 
while(!feof($fp) && $file_count<$file_size){ 
$file_con=fread($fp,$buffer); 
$file_count+=$buffer; 
echo $file_con; 
} 
fclose($fp); 
?>

几点注意事项:

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)的作用:告诉浏览器返回的文件的名称
以上四个Header()是必需的
fclose($fp)可以把缓冲区内最后剩余的数据输出到磁盘文件中,并释放文件指针和有关的缓冲区

PHP 相关文章推荐
PHPWind 发帖回帖Api PHP版打包下载
Feb 08 PHP
PHP函数篇详解十进制、二进制、八进制和十六进制转换函数说明
Dec 05 PHP
PHP中func_get_args(),func_get_arg(),func_num_args()的区别
Sep 30 PHP
解决PhpMyAdmin中导入2M以上大文件限制的方法分享
Jun 06 PHP
php向js函数传参的几种方法
Aug 10 PHP
PHP根据图片色界在不同位置加水印的方法
Jul 01 PHP
Yii框架使用魔术方法实现跨文件调用功能示例
May 20 PHP
php文件上传类的分享
Jul 06 PHP
laravel自定义分页效果
Jul 23 PHP
php实现和c#一致的DES加密解密实例
Jul 24 PHP
thinkPHP利用ajax异步上传图片并显示、删除的示例
Sep 26 PHP
php解析非标准json、非规范json的方式实例
Dec 10 PHP
php异常处理技术,顶级异常处理器
Jun 13 #PHP
PHP的异常处理类Exception的使用及说明
Jun 13 #PHP
PHP抽象类 介绍
Jun 13 #PHP
MySQL 日期时间函数常用总结
Jun 12 #PHP
PHP简洁函数(PHP简单明了函数语法)
Jun 10 #PHP
php数字游戏 计算24算法
Jun 10 #PHP
细谈php中SQL注入攻击与XSS攻击
Jun 10 #PHP
You might like
thinkphp在低版本Nginx 下支持PATHINFO的方法分享
2016/05/27 PHP
thinkphp中多表查询中防止数据重复的sql语句(必看)
2016/09/22 PHP
基于php中echo用逗号和用点号的区别详解
2018/01/23 PHP
找到了一篇jQuery与Prototype并存的冲突的解决方法
2007/08/29 Javascript
jquery 实现input输入什么div图层显示什么
2014/06/15 Javascript
js 操作符汇总
2014/11/08 Javascript
深入探讨javascript函数式编程
2015/10/11 Javascript
js实现选中页面文字将其分享到新浪微博
2015/11/05 Javascript
理解javascript函数式编程中的闭包(closure)
2016/03/08 Javascript
JavaScript实现点击文本自动定位到下拉框选中操作
2016/06/15 Javascript
Node.js v8.0.0正式发布!看看带来了哪些主要新特性
2017/06/02 Javascript
Angular 4中如何显示内容的CSS样式示例代码
2017/11/06 Javascript
React.js绑定this的5种方法(小结)
2018/06/05 Javascript
vue 基于element-ui 分页组件封装的实例代码
2018/12/10 Javascript
vue 集成 vis-network 实现网络拓扑图的方法
2019/08/07 Javascript
解决vue使用vant下拉框van-dropdown-item 绑定title值不变问题
2020/08/05 Javascript
在react-antd中弹出层form内容传递给父组件的操作
2020/10/24 Javascript
如何在vue中使用HTML 5 拖放API
2021/01/14 Vue.js
学习python之编写简单简单连接数据库并执行查询操作
2016/02/27 Python
判断网页编码的方法python版
2016/08/12 Python
Django验证码的生成与使用示例
2017/05/20 Python
Python数据类型之Set集合实例详解
2019/05/07 Python
Python实现操纵控制windows注册表的方法分析
2019/05/24 Python
基于Python2、Python3中reload()的不同用法介绍
2019/08/12 Python
python 装饰器的使用示例
2020/10/10 Python
Python类型转换的魔术方法详解
2020/12/23 Python
HTML5给汉字加拼音收起展开组件的实现代码
2020/04/08 HTML / CSS
Subside Sports德国:足球球衣和球迷商品
2019/06/08 全球购物
实习生求职自荐信
2014/02/07 职场文书
工作证明范本(2篇)
2014/09/14 职场文书
党员个人对照检查材料
2014/10/01 职场文书
运动员加油词
2015/07/18 职场文书
2019交通安全宣传标语集锦!
2019/06/28 职场文书
python 如何执行控制台命令与操作剪切板
2021/05/20 Python
制作能在nginx和IIS中使用的ssl证书
2021/06/21 Servers
探讨Java中的深浅拷贝问题
2021/06/26 Java/Android