文件的上传
文件是如何上传的?你甚至可能好奇它的文件上传的过程是怎么样实现的?其实,对于我们来说,文件的上传过程我们并不需要深入了解,甚至一句话,是不需要管的,权且当文件上传这一个过程是自动完成的就行。
而我们只需要了解到的是,我们上传的文件默认是存放在一个临时的目录里面的(俗称临时路径),说到这里,我们其实要做的就变得很清晰了,我们当务之急要做的就是把这些临时存放的文件移动到我们需要的地方就OK啦!
案例准备:
html框架需要做的上传设置:主要是form标签的属性设置
- action 看需求而定,如果不填,默认就是当前页面,我这里就在当前页面进行提交。
- 需要将请求的method设置为post请求。
- 需要设置编码类型为enctype=multipart/form-data,form表单用了enctype="multipart/form-data"类型后,所有的值都将以二进制的形式进行传递的,都将以这个游戏规则进行。
- form表单中设置隐藏类型的input,其中name值设置为MAX_FILE_SIZE,其中value值设置为需要限制的上传文件的大小(单位字节)
服务器通过PHP处理上传文件,涉及到一些php配置选项(php.ini初始化配置文件,了解即可)
配置项 | 默认值 | 功能描述 |
---|---|---|
file_uploads | On(处于开启状态) | 确定服务器上的PHP脚本是否可以接收HTTP文件上传 |
memory_limit | 128M | 设置脚本可以分配的最大内存量,防止失控脚本独占服务器内存 |
upload_max_filesize | 200M | 限制PHP处理上传文件的最大值,此值必须小于post_max_size的值 |
post_max_size | 200M | 限制通过POST方法可以接受的信息最大量 |
upload_tmp_dir | 临时存放路径 | 上传文件存放的临时路径,可以是一个绝对路径,这个目录对于拥有此服务进程的用户必须是可写的 |
如何查看上述的这些服务器的配置参数?
第一步找到这个配置文件。
如果有你的电脑安装了notepad++编码工具查询起来就很方便。
$_FILES多维数组,用于存储各种与上传有关的信息
$_FILES 获取上传文件的相关信息:文件名、文件类型、文件大小、文件的临时存储路径、文件上传的产生的状态码,0代表文件上传成功
$_FILES["file"]["name"] 客户端文件的原名称,包含拓展名
$_FILES["file"]["size"] 已经上传的文件大小,单位为字节
$_FILES["file"]["tmp_name"] 文件上传后,在服务器存储的临时文件名
$_FILES["file"]["type"] 获取客户端上传文件的格式类型。
$_FILES["file"]["tmp_name"] 文件上传时产生的错误,可以捕捉到的3个状态码,分别为0、1、2、3、4
0:表示文件上传时没有发生任何错误,文件上传成功,很顺利的意思
1:表示上传文件的大小超出了在PHP配置文件中upload_max_filesize选项限制的值
2:表示上传文件大小超出了HTML表单中MAX_FILE_SIZE选项所指定的值
3:表示文件只上传了一部分,有一部分没上传成功。
4:表示没有上传任何的文件。
PHP文件上传处理函数,用于成功上传文件后的后续处理
- is_uploaded_file()函数 判断指定的文件是否是通过HTTP上传的
- move_upload_file()函数 文件上传成功后,会率先存储在服务器的临时目录当中去,这个函数可以让我们将上传在临时路径的文件移到指定的位置。
demo代码:
<?
header('Content-type:text/html;charset=utf-8');
var_dump($_FILES);
?>
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>上传文件</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="uploadFile" />
<input type="submit" name="submit" value="开始上传" />
</form>
</body>
</html>
页面预览和输出的内容:
isset()方法:用于判断该变量是否存在,是否被设置。
完整上传文件的代码:
<?
header('Content-type:text/html;charset=utf-8');
date_default_timezone_set('Asia/Shanghai');//设置东部时区
if(isset($_POST["submit"])) { //判断用户是否点击了开始上传按钮
if(is_uploaded_file($_FILES["uploadFile"]["tmp_name"])){//判断该文件是否是通过HTTP的POST方法上传的
//上传成功
$arr = pathinfo($_FILES["uploadFile"]["name"]); //获取文件名信息
$newFileName = date('YmdGis').rand(1000,9999); //以时间作为文件的命名,随机数避免同一时间的冲突
if(move_uploaded_file($_FILES["uploadFile"]["tmp_name"],"upload/{$newFileName}.{$arr['extension']}")){
//将暂时存储的的上传文件移到新位置,并且拼接上源文件的文件名和拓展名
echo "上传成功!";
}else {
echo "移到文件失败!";
}
}else {
exit("上传失败!");
}
//var_dump($_FILES);//相当于console输出某个对象信息
}
?>
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>上传文件</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="uploadFile" />
<input type="submit" name="submit" value="开始上传" />
</form>
</body>
</html>
可以看到,文件上传成功后,我们的upload文件夹就会多出我们刚刚上传的那个文件,这个文件的名字采用的是当前时间的年月日时分秒的命名方式。
文件的下载
我们知道以.txt文本、.html网页、图片等一些单文件是可以直接在浏览器进行访问到的。
而有一些文件则是比较例外的,比如压缩包文件、word文档、.mp4,必须通过下载到本地,才能进行查看。
但我们在实际的开发中,直接访问文件所放置的位置来是不可取的,因为把详细的路径显示出来表示你已经暴露了,因为你把完整的路径给到了别人,别人就可能有利可图,你的网站就可能会受到攻击风险。
我们正确的做法是做一个桥梁搭路,让访问游客通过这段桥去访问目的端的各种下载文件,避免暴露文件自身的风险。
实际做法很简单,比如让用户直接访问我们的index.php门户页面,然后就可以下载到了文件,这样就避免了用户直接去访问我们的真实文件所在的放置位置。
文件下载的相关处理函数
1.获取文件的MIME类型
<?php
$file = 'chaseTV.zip';//压缩包文件
$fileinfo = finfo_open(FILEINFO_MIME_TYPE); //获取文件MIME类型
//var_dump(finfo_file($fileinfo,$file));//输出所属MIME类型
$mimeType = finfo_file($fileinfo,$file);
finfo_close($fileinfo);//关闭
header('Content-type:'.$mimeType);//设置MIME类型头信息
?>
这里需要开启一个php_fileinfo的拓展,不然会报这个错误:
Fatal error: Call to undefined function finfo_open()
如何开启php_fileinfo的拓展,我会写在文章的最后面。
如果不安装这个拓展也是可以的:我们只需要了解一些常见的MIME类型即可
比如:
.rar压缩包:application/x-rar
.jpg/jpeg图片: image/jpeg
.png图片: image/png
.html超文本: text/html
.txt普通文本: text/plain
.gif图形: image/gif
.zip压缩文件: application/x-zip-compressed
.tar压缩文件: application/x-tar
.css样式表: text/css
.json数据:application/json
1.发送指定的文件MIME类型头信息
header('Content-type:MIME类型');
2.指定下载文件的描述信息
header('Content-Disposition:attachement;filename=文件名称');
3.指定下载文件的大小
header('Content-Length:文件大小');
4.读取文件内容输出至缓冲区
readfile();
案例:
<?php
//以index.php作为访问的桥梁进行伪装模拟,下载用户需要的文件,不暴露真实文件的路径
$file = 'chaseTV.zip';//压缩包文件
header('Content-type:application/x-zip-compressed');//发送指定文件的MIME类型的头信息
//指定下载文件的描述信息
header('Content-Disposition:attachment;filename='.basename($file));
//指定下载文件大小
header('Content-Length:'.filesize($file));
//读取文件的内容输出到缓冲区,返回文件,通俗点理解就是在浏览器下发文件
readfile($file);
?>
这一次,我们不是直接访问文件的所在路径,而是通过index.php作为桥梁,进行匿名访问文件,然后下载。
对比
拓展:
function_exists()函数判断当前系统有没有安装某一个拓展。
<?php
if(!function_exists('finfo_open')){
header('Content-type:text/html;charset=utf-8');
exit('请先开启PHP拓展:fileinfo');
}
$file = 'chaseTV.zip';//压缩包文件
$fileinfo = finfo_open(FILEINFO_MIME_TYPE); //获取文件MIME类型
//var_dump(finfo_file($fileinfo,$file));//输出所属MIME类型
$mimeType = finfo_file($fileinfo,$file);
finfo_close($fileinfo);//关闭
header('Content-type:'.$mimeType);//设置MIME类型头信息
?>
window环境下如何开启php_fileinfo的拓展
声明:我用的是AppServ集成的php环境
- 第一步确认一下你有没有这个php_fileinfo.dll文件
查找路径:D:/AppServ/php5/ext
- 找到php.ini配置文件,右键使用notepad++工具打开
- 点击放大镜输入php_fileinfo进行查找。
-
看到的是绿色代码,因为前面的分号是将代码注释掉了。
-
所以我们要把分号去掉。
- 最后重启apache服务器或者直接重启电脑。
-
查看file_info拓展是否开启,输入phpinfo.php进行页面访问,查看配置信息。
-
找到F打头的配置信息,看到fileinfo拓展,确认file_info拓展处于enabled开启状态。
到这里我们就可以使用php的finfo_open函数来查看文件MIME类型。
$file = 'chaseTV.zip';//压缩包文件
$fileinfo = finfo_open(FILEINFO_MIME_TYPE); //获取文件MIME类型
var_dump(finfo_file($fileinfo,$file));//输出所属MIME类型