php文件与目录操作:文件上传和文件下载

文件的上传

文件是如何上传的?你甚至可能好奇它的文件上传的过程是怎么样实现的?其实,对于我们来说,文件的上传过程我们并不需要深入了解,甚至一句话,是不需要管的,权且当文件上传这一个过程是自动完成的就行。

而我们只需要了解到的是,我们上传的文件默认是存放在一个临时的目录里面的(俗称临时路径),说到这里,我们其实要做的就变得很清晰了,我们当务之急要做的就是把这些临时存放的文件移动到我们需要的地方就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++工具打开
    image.png
  • 点击放大镜输入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类型
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容