小米技术社区
小米技术社区管理员 关于小米

27岁,山西运城人,职业电商经理人,前端开发工作者,从事过网站建设、网络推广、SEO、SEM、信息流推广、二类电商、网络运维、软件开发,等相关电商工作,经验较为丰富,小米技术社区致力于为广大从事Web前端开发的人员提供一些力所能及的引导和帮助 ...[更多]

E-mail:mzze@163.com

Q Q:32362389

W X:xiaomi168527

小米技术社区大牛王飞 关于王飞

27岁,山西运城人,职业电商经理人,网络工程师兼运维,从事过运营商网络建设,企业网络建设、优化。数据中心网络维护等通过,经验丰富,座右铭:当自己休息的时候,别忘了别人还在奔跑。 ...[更多]

E-mail:wf_live@126.com

Q Q:3940019

微博:王小贱ss

小米技术社区设计小艳 关于小艳

大于花一样的年龄,河南郑州是我家,2010年在北京接触团购网,2011年进入天猫淘宝一待就是四年,如今已经将设计走向国际化(ps:误打误撞开始进入阿里巴巴国际站的设计,嘿嘿)五年电商设计,丰富经验,从事过天猫淘宝阿里各项设计,店铺运营,产品拍摄;我将我的经历与您分享是我的快乐!座右铭:越努力越幸运! ...[更多]

E-mail:97157726@qq.com

Q Q:97157726

标签云
精品推荐
您的位置:首页 > 后端编程 > PHP > PHP基础

PHP文件编程--文件的上传和服务器的接收

分类: PHP基础54个赞

PHP文件编程--文件的上传

开发中需要上传图片、音乐、视频等等,这种上传传递是二进制数据。


客户端上传文件

HTML文件域

<input type="file" name="image" enctype="multipart/form-data">
//enctype="multipart/form-data" 必须设置


表单的enctype属性

默认情况下,表单传递是字符流,不能传递二进制流,通过设置表单的enctype属性传递复合数据。


enctype属性的值有:

1. application/x-www-form-urlencoded:【默认】,表示传递的是带格式的文本数据。

2. multipart/form-data:复合的表单数据(字符串,文件),文件上传必须设置此值

3. text/plain:用于向服务器传递无格式的文本数据,主要用户电子邮件


相关单词

multipart:复合

form-data:表单数组


服务器接受文件

服务器文件的接收需要写了解$_FILES超全局变量

超全局变量$_FILES是一个二维数组,用来保存客户端上传到服务器的文件信息。二维数组的行是文件域的名称,列有5个。

1、$_FILES[][name]:上传的文件名

2、$_FILES[][type]:上传的类型,这个类型是MIME类型(image/jpeg、image/gif、image/png)

3、$_FILES[][size]:文件的大小,以字节为单位

4、$_FILES[][tmp_name]:文件上传时的临时文件

5、$_FILES[][error]:错误编码(值有0、1、2、3、4、6、7)0表示正确


表单允许的最大上传值

$_FILES[][error]的详解:

注意:没有5

错误描述
0正确
1文件大小超过了php.ini中允许的最大值    upload_max_filesize = 2M
2文件大小超过了表单允许的最大值
3只有部分文件上传
4没有文件上传
6找不到临时文件
7文件写入失败

重点掌握的错误号:0和4

注意:值2的意思是下图;MAX_FILE_SIZE必须在文件域的上面。

MAX_FILE_SIZE设置


将上传文件移动到指定位置

move_uploaded_file(临时地址,目标地址)

注意:上传的同名的文件会覆盖

<body>
<?php
if(!empty($_POST)) {
    if($_FILES['face']['error']==0){  //上传正确
        //文件上传
        move_uploaded_file($_FILES['face']['tmp_name'],'./'.$_FILES['face']['name']);
    }else{
        echo '上传有误';
        echo '错误码:'.$_FILES['face']['error'];
    }
}
?>
<form method="post" action="" enctype='multipart/form-data'>
    <input type="file" name="face">
    <input type="submit" name="button" value="上传">
</form>
</body>


与文件上传有关的php.ini配置

post_max_size = 8M:表单允许的最大值

upload_max_filesize = 2M:允许上传的文件大小

upload_tmp_dir =F:\wamp\tmp:指定临时文件地址,如果不知道操作系统指定

file_uploads = On:是否允许文件上传

max_file_uploads = 20:允许同时上传20个文件


优化文件上传

1.更改文件名

方法一:通过时间戳做文件名

<?php
$path='face.stu.jpg';
//echo strrchr($path,'.');  //从最后一个点开始截取,一直截取到最后
echo time().rand(100,999).strrchr($path,'.');

方法二:通过uniqid()实现

$path='face.stu.jpg';
echo uniqid().strrchr($path,'.'),'<br>';   //生成唯一的ID
echo uniqid('goods_').strrchr($path,'.'),'<br>';   //带有前缀
echo uniqid('goods_',true).strrchr($path,'.'),'<br>';  //唯一ID+随机数



2.验证文件格式

方法一:判断文件的扩展名(但是不能识别文件伪装)

操作思路:将文件的后缀和允许的后缀对比


<body>
<?php
if(!empty($_POST)) {
    $allow=array('.jpg','.png','.gif'); //允许的扩展名
    $ext=strrchr($_FILES['face']['name'],'.');  //上传文件扩展名
    if(in_array($ext,$allow))
        echo '允许上传';
    else
        echo '文件不合法';
}
?>
<form method="post" action="" enctype='multipart/form-data'>
    <input type="file" name="face">
    <input type="submit" name="button" value="上传">
</form>
</body>



注意:比较扩展名不能防止文件伪装,容易被攻陷。


方法二:通过`$_FIELS[]['type']`类型(不能识别文件伪装)

<body>
<?php
if(!empty($_POST)) {
    $allow=array('image/jpeg','image/png','image/gif'); //允许的类别
    $mime=$_FILES['face']['type'];  //上传文件类型
    if(in_array($mime,$allow))
        echo '允许上传';
    else
        echo '文件不合法';
}
?>
<form method="post" action="" enctype='multipart/form-data'>
    <input type="file" name="face">
    <input type="submit" name="button" value="上传">
</form>
</body>

注意:比较`$_FIELS[]['type']`不能防止文件伪装,同样容易被攻陷。


方法三:用php_fileinfo扩展(可以防止文件伪装)

在php.ini中开启fileinfo扩展

注释去掉extension=php_fileinfo.dll

注意:开启fileinfo扩展以后,就可以使用finfo_*的函数了

开启fileinfo扩展

<body>
<?php
if(!empty($_POST)) {
    //第一步:创建finfo资源
    $info=finfo_open(FILEINFO_MIME_TYPE);
    //var_dump($info);      //resource(2) of type (file_info) 
    //第二步:将finfo资源和文件做比较
    $mime=finfo_file($info,$_FILES['face']['tmp_name']);
    //第三步,比较是否合法
    $allow=array('image/jpeg','image/png','image/gif'); //允许的类别
    echo in_array($mime,$allow)?'合法':'不合法';
}
?>
<form method="post" action="" enctype='multipart/form-data'>
    <input type="file" name="face">
    <input type="submit" name="button" value="上传">
</form>
</body>

小结:验证文件格式有三种方法

1、可以验证扩展名(不可以防止文件伪装)

2、通过`$_FILES[]['type']`验证(不可以防止文件伪装)

3、通过file_info扩展(可以防止文件伪装,推荐)



综合demo:

优化文件上传

步骤

第一步:验证是否有误

第二步:验证格式

第三步:验证大小

第四步:验证是否是http上传

第五步:上传实现

<body>
<?php
/**
*验证错误
*如果有错,就返回错误,如果没错,就返回null
*/
function check($file) {
    //1:验证是否有误
    if($file['error']!=0){
        switch($file['error']) {
            case 1:
                return '文件大小超过了php.ini中允许的最大值,最大值是:'.ini_get('upload_max_filesize');
            case 2:
                return '文件大小超过了表单允许的最大值';
            case 3:
                return '只有部分文件上传';
            case 4:
                return '没有文件上传';
            case 6:
                return '找不到临时文件';
            case 7:
                return '文件写入失败';
            default:
                return '未知错误';
        }
    }
    //2、验证格式
    $info=finfo_open(FILEINFO_MIME_TYPE);
    $mime=finfo_file($info,$file['tmp_name']);
    $allow=array('image/jpeg','image/png','image/gif'); //允许的类别
    if(!in_array($mime,$allow)){
        return '只能上传'.implode(',',$allow).'格式';
    }
    //3、验证大小
    $size=123456789;
    if($file['size']>$size){
        return '文件大小不能超过'.number_format($size/1024,1).'K';
    }
    //4、验证是否是http上传
    if(!is_uploaded_file($file['tmp_name']))
        return '文件不是HTTP POST上传的<br>';

    return null;  //没有错误
}

//表单提交
if(!empty($_POST)) {
    //上传文件过程中有错误就显示错误
    if($error=check($_FILES['face'])){
        echo $error;
    }else{
        //文件上传,上传的文件保存到当天的文件夹中
        $foldername=date('Y-m-d');      //文件夹名称
        $folderpath="./uploads/{$foldername}";    //文件夹路径
        if(!is_dir($folderpath))
            mkdir($folderpath);
        $filename=uniqid('',true).strrchr($_FILES['face']['name'],'.'); //文件名
        $filepath="$folderpath/$filename";    //文件路径
        if(move_uploaded_file($_FILES['face']['tmp_name'],$filepath))
            echo "上传成功,路径是:{$foldername}/{$filename}";
        else
            echo '上传失败<br>';
    }

}
?>
<form method="post" action="" enctype='multipart/form-data'>
    <input type="file" name="face">
    <input type="submit" name="button" value="上传">
</form>
</body>

运行结果

image.png

小结:

1、将时间戳转换格式

echo date('Y-m-d H:i:s',1231346),'<br>';    //将时间戳转成年-月-日 小时:分钟:秒
echo date('Y-m-d H:i:s'),'<br>';      //将当前的时间转成年-月-日 小时:分钟:秒

2、使用date需要在php.ini设置时区;默认是东1区,设置成为PRC,即为东八区

在PHP.INI中设置时区

3、PHP的执行可以不需要Apache的参与

PHP独立执行结果


小米技术社区

本站内容均为小米原创,转载请注明出处:小米技术社区>> PHP文件编程--文件的上传和服务器的接收