开发企业网站9 -- 文件上传

2019-10-18  本文已影响0人  潘肚饿兵哥哥

\color{rgba(254, 67, 101, .8)}{上传同样的需要html页面显示和php文件处理业务}
\color{rgba(254, 67, 101, .8)}{在上传文件页面,html原来是这样:}

<h3>上传文件</h3>
<from action="upload.php" method="post" >
<p>
  <input type="file" name="file">
</p>
<p>
  <button>提交</button>
</p>

\color{rgba(254, 67, 101, .8)}{用post提交,然后类型是file,这个表单的名字是file}
\color{rgba(254, 67, 101, .8)}{在php文件里,接收文件名为file的数据}

<?php 
  $file=$_POST['file'];
?>

\color{rgba(254, 67, 101, .8)}{这是之前的做法,但是这里还是这样做的话}
\color{rgba(254, 67, 101, .8)}{例如上传一张图片,就只会接收到图片名称,图片内容是接收不到的}
\color{rgba(254, 67, 101, .8)}{在form里这样改}

添加enctype="multipart/form-data"

<h3>上传文件</h3>
<from action="upload.php" method="post"  enctype="multipart/form-data">
<p>
  <input type="file" name="file">
</p>
<p>
  <button>提交</button>
</p>

定义和用法
enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。

默认地,表单数据会编码为 "application/x-www-form-urlencoded"。就是说,在发送到服务器之前,所有字符都会进行编码(空格转换为 "+" 加号,特殊符号转换为 ASCII HEX 值)。

image.png

\color{rgba(254, 67, 101, .8)}{上传文件需要用这个属性,但使用了这个属性之后,会报错}
\color{rgba(254, 67, 101, .8)}{因为之前是用post接收的file类型}
\color{rgba(254, 67, 101, .8)}{这里加了enctype 属性之后,file就不管用了}
\color{rgba(254, 67, 101, .8)}{文件域里的file用post接收就不行了}
\color{rgba(254, 67, 101, .8)}{需要用另外一个系统预处理超全局数组}

$GLOBALS
$_SERVER
$_REQUEST
$_POST
$_GET
$_FILES:    HTTP 文件上传变量
$_ENV
$_COOKIE
$_SESSION

\color{rgba(254, 67, 101, .8)}{用files变量来接收}

<?php 
  $file = $_FILES['file'];
?>

\color{rgba(254, 67, 101, .8)}{用enctype属性编码后,用files数组接收文件,接收到的数组就不只是一个文件名}
\color{rgba(254, 67, 101, .8)}{而是一个带着文件名、文件类型和文件路径的数组}
\color{rgba(254, 67, 101, .8)}{还有是否报错和文件大小}
\color{rgba(254, 67, 101, .8)}{这个路径是服务器的路径,文件已经传到服务器里面了}
\color{rgba(254, 67, 101, .8)}{此时是以临时文件的形式放在这里}
\color{rgba(254, 67, 101, .8)}{文件上传就是把这个临时文件移动到需要的地方去}
\color{rgba(254, 67, 101, .8)}{在移动的过程中,要更改文件名}
\color{rgba(254, 67, 101, .8)}{因为不知道是模板还是什么会改动文件名后再保存为临时文件}
\color{rgba(254, 67, 101, .8)}{这就实现了上传}

移动:
move_uploaded_file(要移动的路径,要移动的内容(文件名));

\color{rgba(254, 67, 101, .8)}{文件上传html页面代码}

<!DOCTYPE html>
<html lang="en">
<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>Document</title>
</head>
<body>
    <H3>上传文件</H3>
    <!-- 上传要用post   -->
    <form action="../../admin/upload.php" method="post" enctype="multipart/form-data" />
        <p>
            <input type="file" name="file">
        </p>
        <p>
            <button>提交</button>
        </p>
    </form>
</body>
</html>
image.png

\color{rgba(254, 67, 101, .8)}{文件上传php文件}

<?php
    // 调用这个函数这样写:$ret是接收到的函数的返回值
    // 这个返回值有两个,一是成功或失败,二是如果失败,是什么原因失败
    // 如果不是写成一个函数,那这个if和die就可以写在代码中
    // 但是如果要封装函数,就要在外面写
    // 如果上传成功,就显示图片(路径,url)
    $ret = upload('file');
    if($ret['error'] == 1){
        die($ret['message']);
    }else{
        echo "<img src='{$ret['url']}' />";
    }




    //将这段上传文件代码封装成一个函数
    function upload($name, $path='uploads', $allow_type=['jpg', 'png', 'gif'], $max_size=2*1024*1024){
        // 在上传页面填的文件名是file,所以在这里接收这个名叫file的文件
        $file = $_FILES[$name];


        //在接收上传文件之前,需要进行一些限制,不能用户上传什么我们就接收什么
        // 首先要判断用户有没有上传文件,如果没有,就显示提示信息后终止执行程序
        // 返回值有两个,但是只能写一个return,就用关联数组,如果上传失败,返回值是1
        if(!empty($file['name'])){
            return ['error'=>1, 'message'=>'没有上传文件'];
        }


        //strrchr() 函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。
        // 用于获取上传文件的后缀,下面这行代码表示获取文件名点后面的内容
        $suffix = strrchr($file['name'], '.');



        // 如果用户上传了文件,那么需要进行判定是不是允许的文件类型,那就先要写好允许上传的文件是哪些
        // 有两个办法可以完成,一是上传的文件信息中有一个type,type中就带有文件格式信息,但是这种麻烦,因为文件类型太多,所以用第二中办法
        // 先写好一个数组,把允许上传的文件类型都写在数组中,只要上传的文件不是这几种格式就禁止上传
        // 用in_array();函数判断接收到的文件类型在不在这个数组中,在就允许上传,不在就禁止
        // 上面$suffix变量取得的后缀是带点的,要把这个点去掉,用substr();函数截取从下标1开始的内容,第0位就是点
        // 但是这个变量如果这样写,这段代码就只能上传图片,所以不在这里写了,把它通过传参的形式来传,可以拓展这个函数的适用范围
        //$allow_type = ['jpg', 'png', 'gif'];
        if(in_array(substr($suffix, 1), $allow_type)){
            return ['error'=>1, 'message'=>'文件类型不允许'];
        }


        // 用户上传文件的大小也需要进行限制,1024*1024就是1M
        // 配置文件php.ini文件中(upload_max_filesize)默认上传的大小限制就是2M,如果需要更大,要先改配置文件
        // 这里尺寸写死了就没法改了,通过给函数传参的形式可以灵活设置尺寸大小
        // $max_size = 2*1024*1024;
        if($file['size'] > $max_size){
            return ['error'=>1, 'message'=>'上传文件不能超过2M'];
        }


        // 上传文件必须要从html页面提交来,否则不接收
        // is_uploaded_file();判断文件是否用post或get上传
        if(!is_uploaded_file($file['tmp_name'])){
            return ['error'=>1, 'message'=>'非法上传'];
        }
    

        // 文件先建一个文件夹uploads,然后再建一个子文件夹用年月日格式命名,用于装移动过来的文件(上传的文件)
        // 这里如果这样写,路径也写死了,文件夹名就不能改了,所以,文件夹名也用传参的方式传进来
        // $path = 'uploads/'.date('Ymd').'/';
        $path = $path.'/'.date('Ymd').'/';


        // 首先判断这个保存文件的路径存不存在,用is_dir这个函数进行判断
        if(!is_dir($path)){
            // 如果目录不存在,就创建一个目录
            // 创建目录函数: mkdir(目录,权限,是否递归创建(缺省为否));
            // 权限,windows系统不限,linux不能乱填,所以为了通用,要按规则填,目录一般填0755,文件一般填0644,就是没有执行权限
            // 0755是八进制,每一个数代表一个权限,每一个目录都有三种角色:所有者、所有组、其他人
            //每一个文件、目录都有三个权限,读、写、执行,用数字代替就是读4,写2,执行1,就是2的0次方,1次方,2次方
            /*
                        读4    写2    执行1
            所有者
            所有组
            其他人
            0755就是这三个数的组合
            */
            //递归创建目录就是能不能创建多级目录,默认不允许

            mkdir($path, 0755, true);
        }

        // 这里文件名和文件类型都不能写死了,因为文件类型不同,而且文件名不能重名
        // $filename = $path.'1.jpg';
        // 文件名用年月日时分秒,并且每秒中之内产生的文件名再用随机数生成一个数,之后md5加密
        //文件后缀名要在前面$_FILES之后进行接收
        $filename = $path.md5(date('YmdHis').mt_rand(10, 99)).'.$suffix';


        // 上传其实就是把一个文件移动到另一个文件夹中去
        // 如果成功返回值0,并且返回路径,如果失败,返回值1,并提示上传失败
        if(move_uploaded_file($file['tmp_name'], $filename)){
            return ['error' => 0, 'url' => 'filename'];
        }else{
            return ['error'=>1, 'message'=>'上传失败'];
        }
    }
        
    
?>
上一篇下一篇

猜你喜欢

热点阅读