3,PHP上传下载
前言
上传文件的应用场景很多,数不胜数,最典型的,就是图片上传了。
文件上传,可以简单的学,也可以复杂的学。可以知其然,也可以知其所以然。
网络上针对PHP的文件上传有许许多多的“实现”教程,但对于原理方面的讲解却很少。
所以本人自认为才思敏捷,便斗胆推敲一二。
觉得好的,捧场点赞皆可,觉得渣的,留言抨击亦可。
有不对的地方,还请大神指出。
接下来,本文就针对PHP文件上传的实现流程,来一一做出分析。
目录
- 简介
- $_FILES
- php.ini的相关配置
- 错误码
- 持久保存文件
- ThinkPHP upload 的成员
- 下载
简书的markdown无法添加当页锚点,所以就不做跳转了。
(哪位前辈如果知道怎么添加,小弟跪求指教!)
简介
首先,我把整个上传流程中参与的角色都拎出来,再做一一分析。
- 浏览器:无论是file框,还是向服务器提交请求,都是浏览器在做底层支持。如,把文件转换为文件流,就由它代劳了。
- HTML:上传文件,我们需要form表单,post提交,以及编码enctype="multipart/form-data"
- HTTP:
- 这个很重要,大家都知道,http协议是一个基于TCP且无状态的交互方式,也就是俗称的短连接。
- 也正因为http的特性,所以上传文件就只能以文件流的形式提交(完整提交),他没办法像FTP那样,直接拷贝文件到服务器。
- 服务端:
- 这个应该算是一个集合,如LAMP、WAMP等,也可以是其他的语言平台
- 解析流程与其他PHP脚本一样,唯一不同的就是对文件流的处理
- 当服务端接收到外部请求时,会根据你的enctype来确定你是在上传文件,再将文件流生成文件,保存到规定的临时目录中
- 最后根据文件信息生成$_FILES变量(本行特指PHP)
PHP基于HTTP的文件上传.png本屌丝不才,文字讲解比较生硬,所以特献上一张流程图,来将此流程描述清楚。
由上图可加,在这个流程之中,最关键的,就是文件流了。而文件流,则是在浏览器解析表单的时候,自动获取并提交的。
这也是为什么,有些人想要异步上传文件的时候,直接把form序列化或直接取input的value时,无法成功的原因了。
(异步上传的做法,本文暂不讨论)
$_FILES
这是PHP提供的一个预定义变量,格式是二维数组(并不一定)。
Array(
input_name=>array(
name=>上传的文件名,
type=>上传的文件MIME类型,
tmp_name=>上传服务器上的临时文件名
size=>上传文件的大小
error=>上传文件的错误号
)
)
如上,是它的结构。
其中,input_name就是HTML表单中file框所指定的name值
$_FILES的结构是多变的,它并不永远都保持一个二维数组的样子。
如,你的file框开启了文件多选,又或者,你提交的一个表单中,存在好几个文件,具体结构,视情况而定。
php.ini的相关配置
// 直接配置
File_uploads = on 支持通过http上传文件
Upload_tmp_dir = , 临时文件存放目录
Upload_max_filesize = 2M 允许上传的最大值
Max_file_uploads=20 允许一次上传最大的文件数
Post_max_size=8M post方式发送数据的最大值
// 相关配置
max_execution_time = -1 设置了脚本被解析器终止之前,允许的最大执行时间,单位为秒
max_input_time = 60 脚本解析输入数据允许的最大时间,单位为秒
max_input_nesting_level = 64 设置输入变量的嵌套深度
max_input_vars = 1000
接受多少输入的变量,限制分别应用于$_GET,$_POST和$_COOKIE
即,get和post最多只允许传入1000个变量
memory_limit = 128M 最大单线程独立的内存使用量
错误码
0:上传成功(上传到临时目录)
1:文件超过upload_max_filesize的限制
2:上传文件大小超过了HTML表单中MAX_FILE_SIZE指定的值
3:文件只有部分被上传
4:没有文件被上传
6:找不到临时文件夹
7:文件写入失败
8:上传的文件被PHP扩展程序中断
持久保存文件
实际上,在我们得到$_FILES之前的流程,在“简介”中,已经描述过了。
所以,排除上传出错的情况之外,我们已经知道,在截止到得到$_FILES这一步,上传的所有文件都还保存在临时目录里面。
既然称之为临时目录,那么我们的文件当然不能一直放在那里。
所以,我们需要将文件持久保存到符合我们系统逻辑的、正确的目录中。
这一步其实很简单,有两个方法:
方式一:move_uploaded_file($tmp_name,’uploads/’.’$filename’);
方式二:copy($tmp_name,’uploads/’.’$filename’);
但是你必须保证PHP所使用的帐号,有权限在该文件夹下写文件,特别是Linux系列的环境。
ThinkPHP upload 的成员
Upload.png
下载
主要用于提示浏览器,下载一些支持格式的文件,如html,php,png等
$filename = ’1.jpg’;
$file = ’./1.jpg’;
header(’content-disposition:attachment;filename=’.$file); // 下载时浏览器显示的文件名
header(’content-length:’.filesize($file));
结语
上传下载的应用非常广泛,实现层次,其实也不用重复造轮子,理解思路,再直接使用现成的类就可以了。