zoukankan      html  css  js  c++  java
  • (独孤九剑)--文件上传

    【一】文件上传

    场景:上传博客,文章,图片,人脸扫描等

    【二】配置文件

    (1)配置项   

    fille_uploads         开启上传功能on;关闭上传功能off;

    post_max_size     系统允许post传参最大值

    upload_max_filesize    系统允许上传文件最大值

    memory_limit               内存使用限制

    建议尺寸:上传文件大小 < upload_max_filesize < post_max_size < memory_limit

    (2)拓展

    此外,还可以配置临时文件的存储位置。

    临时目录中的临时文件有效期默认为脚本周期,即一次请求结束

    【三】表单数据类型

         表单数据类型有两种:

         (1)字符串类型(字节流编码);

         (2)文件类型(二进制编码);

         *原因解析*表单提交时:浏览器会默认的认为,表单内数据都是字符串类型(即使使用file文件域)。通过在form上增加enctype属性,告知浏览器表单内的数据不仅有字符串,还有文件。从而进行文件提交

         上传图片和博客时需要设置上传内容类型为为禁止编码:multipart/form-data

          <form> 标签的 enctype 属性规定了在提交表单时要使用哪种内容类型。在表单需要二进制数据时,比如文件内容,请使用 "multipart/form-data"

    【四】提交时服务器处理方式

            接受浏览器请求时,处理好表单内数据。根据数据类型不同(2种),采用不同处理方式

            ①字符串类型/字节流,存储在$_POST变量里(内存里)

            ②文件型数据/二进制,存储在上传临时目录中

    【五】错误类型

    每个上传的临时文件都有 5个信息:name原始文件名;type类型;tmp_name临时地址;error是否有错及错误类型;size大小

    <form action="" method="post" enctype="multipart/form-data">
        <input type="file" name="file" id="file" />
        <input type="submit" name="submit" value="提交" />
    </form>
    <?php
        echo "<pre>";
        var_dump($_FILES);
        echo "</pre>";
    ?>

    提交后输出数组:

    array(1) {
      ["file"]=>
      array(5) {
        ["name"]=>
        string(10) "零食.txt"
        ["type"]=>
        string(10) "text/plain"
        ["tmp_name"]=>
        string(22) "C:WindowsphpAD25.tmp"
        ["error"]=>
        int(0)
        ["size"]=>
        int(443)
      }
    }

    下面说下错误类型:01234567

    0:无错误;

    1:文件过大,大于PHP配置upload_max_filesize

    2:文件过大,超过表单元素max_file_size

    3:上传部分文件

    4:没有上传文件

    5:上传空文件

    6:没有找到临时上传文件(权限控制)

    7:临时文件写入失败

    【六】案例:上传预览图片

    <!DOCTYPE html>
    <html>
    <head>
    <title>PHP测试demo</title>
    <link rel="stylesheet" href="./demo.css">
    <style type="text/css">
     #preview{
                display: block;
                width: 100px;
                height: 100px;
                border:1px solid red;
     }
    </style>
    </head>
    <body>
    <form action="index.php" method="post" enctype="multipart/form-data">
    <label for="file">文件名:</label>
    <input type="file" name="file" id="file" />
    <img id="preview" src=<?php echo "./upload/".$_FILES["file"]["name"]?> alt="点击上传图片"/>
    <br />
    <input type="submit" name="submit" value="提交" />
    </form>
    <?php
    //name原始文件名;type类型;tmp_name临时地址;error是否有错及错误类型;size大小
    if ((($_FILES["file"]["type"] == "image/jpg")|| ($_FILES["file"]["type"] == "image/jpeg") || ($_FILES["file"]["type"] == "image/pjpeg"))){ if ($_FILES["file"]["error"] > 0){ echo "报错: " . $_FILES["file"]["error"] . "<br />"; }else{ echo "文件名: " . $_FILES["file"]["name"] . "<br />"; echo "类型: " . $_FILES["file"]["type"] . "<br />"; echo "大小: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />"; echo "原先保存位置: " . $_FILES["file"]["tmp_name"]."<br>"; //保存 if (file_exists("./upload/" . $_FILES["file"]["name"])){ echo "注意:该文件". $_FILES["file"]["name"] . "已经存在!!!"; }else{ move_uploaded_file($_FILES["file"]["tmp_name"], "./upload/" . $_FILES["file"]["name"]); echo "提交后保存位置: " . "./upload/里的" . $_FILES["file"]["name"]; } } }else{ echo "Invalid file文件类型不符"; }//注意路径,例如../php7/a仍然是保存到php7里,想要保存到php7下的a文件里的话需要 路径为../php7/a/ ?> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script type="text/javascript"> window.FileToSrc = function (file) { if (window.URL) return window.URL.createObjectURL(file); if (window.windcreateObjectURL) return window.createObjectURL(file); if (window.webkitURL) return window.webkitURL.createObjectURL(file); }; $('#file').on('change', function(){ //获取文件列表对象 var fileList = $('#file')[0].files; //创建文件流获取文件地址 var src =FileToSrc(fileList[0]); //设置图片路径 $("#preview").attr("src", src); }); </script> </body> </html>

    【七】上传步骤

    (1)判断是否有错误码

    $_FILES["file"]["error"]读取错误类型

      0为无错误,1234567为有错误

    if ($_FILES["file"]["error"] > 0){
        echo "报错: " . $_FILES["file"]["error"] . "<br />";
    }else{
        ...
    }    

    (2)自定义判断文件大小是否超标

    除了php.int中规定的上传最大值外,通常还需要设定业务规定的上传大小限制

    例如:新浪微博或QQ空间头像图片规定限制2M,而上传时又可以超过2M

    此处的判断文件大小,用于限制实际业务里想要规定的实际文件大小

    (3)判断后缀名和mime类型是否符合

    黑客可以在图片里植入病毒,在附件里上传病毒,会在网页里插入病毒或者诱惑性图片。所以,我们需要上传文件后缀和mime类型都要进行判断才行

    mime类型是多用途互联网邮件扩展类型,设定某种扩展名的文件用一种应用程序来打开的方式类型,当扩展文件名被访问时,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

    在判断后缀和MIME类型的时候,会用到PHP的in_array(判断的值,范围数组)函数,该函数需要用到两个参数

    我们用in_array()来判断文件的后缀名和mime类型是否在允许的范围内

    (4)生成文件名

    文件上传成功后,一般不会让它保存原名。

    因为有些人在原名里添加了敏感关键词,会违反国家相关法律

    所以采用date()、mt_rand()、unique()生成随机文件名

    (5)判断是否是上传文件

    (6)移动临时文件到指定位置

    <?PHP
    header("content-type:text/html;charset=utf-8");
    if(!empty($_FILES[up_picture][name])){                                       //判断上传文件是否为空
        if($_FILES['up_picture']['error']>0){                                    //判断文件是否可以上传到服务器
            echo "上传错误";
            switch($_FILES['up_picture']['error']){
                case 1:
                    echo "上传文件大小超出配置文件规定值";
                    break;
                case 2:
                    echo "上传文件大小超出表单中约定值";
                    break;
                case 3:
                    echo "上传文件不全";
                    break;
                case 4:
                    echo "没有上传文件";
                    break;
            }
        }else{
            if(!is_dir("./upfile/")){                                           //判断指定目录是否存在
                mkdir("./upfile/");                                             //创建目录
            }
            $path='./upfile/'.time().strstr($_FILES['up_picture']['name'],'.');//定义文件名称和存储位置
            if(is_uploaded_file($_FILES['up_picture']['tmp_name'])){           //判断是否通过HTTP POST上传的
                if(!move_uploaded_file($_FILES['up_picture']['tmp_name'],$path)){       //执行上传
                    echo "上传失败";
                }else{
                    echo "文件".time().$_FILES['up_picture']['name']."上传成功,大小为:".$_FILES['up_picture']['size'];
                }
            }else{
                echo "上传文件".$_FILES['up_picture']['name']."不合法!";
            }
        }
    }
    ?>

    【八】步骤解析

    (1)判断错误码

    if ($_FILES['myfile']['error'] > 0) {
            switch ($_FILES['file']['error']) {
                case '1':
                    echo "文件过大";
                    break;
                case '2':
                    echo "文件超出指定大小";
                    break;
                case '3':
                    echo "只上传了部分文件";
                    break;
                case '4':
                    echo "没有上传文件";
                    break;
                case '5':
                    echo "上传空文件";
                    break;
                case '6':
                    echo "没有找到临时上传文件(权限问题)";
                    break;
                case '7':
                    echo "临时文件写入失败";
                    break;
            }
        }else{
            echo "无错误";
        }

    (2)判断文件是否超出大小

    实际项目中由于系统硬件的限制,以及存储设备的限制,不可能让用户无限上传文件。所以要对用户上传的文件大小进行限制,能让应用平稳运行

    将文件大小上限定义为$MAX_FILE_SIZE,若文件大小大于$MAX_FILE_SIZE则退出上传并错误提示

    if ($_FILES['myfile']['error'] > 0) {
            exit("系统出错0,1,2,3,4,5,6,7");
        }else{
            $MAX_FILE_SIZE = 1000;
            if ($_FILES['myfile']['size'] > $MAX_FILE_SIZE) {
                exit('文件超出指定大小');
            }
        }

    (3)判断文件的mime类型是否正确

    例如要求上传后缀名为GIF或jpg的文件,当上传不符合要求的文件时返回错误提示

    注意:文件类型限制前端即可限制,后端也行

    例如:要求只能上传图片

    前端限制:选择文件时只会出现图片选项

    <input type="file" name="myfile" id="file" accept="image/*"/>

    后端限制:选择文件时随意,上传时判断进行限制

    $allow = array('jpg','gif');//规定允许的类型
            $myImg = explode('.', $_FILES['myfile']['name']);//explode()将字符串打散为数组
            $suffix = array_pop($myImg);//array_pop删除数组末尾元素
            if (!in_array($suffix, $allow)) {
                exit("文件后缀名不符合");
            }else{
                echo "开始上传";
            }

    或者用数组简单处理

    $allow =array("image/jpg","image/jpeg","image/pjqeg","img/gif");
    if (!in_array($_FILES['myfile']['type'], $allow)) {
          exit(文件格式不正确,请检查);
    }else{
          echo "开始上传";
    }

    (4)生成指定文件路径和文件名

    为了避免文件名重复造成的错误,可以按照一定格式生成随机文件名

    $path = "upload/imgs/";
    $name = date('y').date('m').date('d').date('h').date('i').date('s').rand(0,9).'.'.'. $suffic';
    //date('y').date('m').date('d').date('h').date('i').date('s')按照日期生成随机数
    //rand()生成指定范围的随机数

    (5)判断是否上传文件

    if (is_uploaded_file($_FILES['myfile']['tmp_name'])) {
        ...
    }

    (6)移动文件到指定位置

    使用move_uploaded_file(filename, destination)将文件移动到指定位置保存

    if(is_uploaded_file($_FILES['myfile']['tmp_name'])){
                if (move_uploaded_file($_FILES['myfile']['tmp_name'], $path. $name)) {
                    echo "上传成功";
                }else{
                    echo "上传失败";
                }
            }else{
                echo "不是上传文件";
            }

    【九】多文件上传

    (1)可以使用$_FILES来接受文件信息,打印并查看数组

    <form action="" method="post" enctype="multipart/form-data">
        <input type="file" name="file[]"/><hr>
        <input type="file" name="file[]"/><hr>
        <input type="submit" name="submit" value="提交" />
    </form>
    <?php
        echo "<pre>";
        var_dump($_FILES['file']);
        echo "</pre>";
    ?>

    (2)多文件时,从打印数据可以看出文件信息被存到数组里。这时需要用到循环来读取单个文件的信息。

    $array = $_FILES['file']['name'];
        $length = count($array);
        for($i=0;$i<$length;$i++){
            echo "文件名为".$array[$i]."<br>";
            echo "原先保存位置: " . $_FILES["file"]["tmp_name"][$i]."<br>";
            move_uploaded_file($_FILES["file"]["tmp_name"][$i],"./upload/" . $array[$i]);
            echo "提交后保存位置: " . "./upload/里的" . $array[$i]."<br>";
        }

    注意:临时文件名后需加[$i]来进行区分辨别

    【十】文件上传进度处理

    在PHP的5.4版本之前,需要安装额外的扩展才能监控到文件上传进度。

    5.4版本之后,引入了session.upload_progress的新特性,只需要在php.int里开启配置,即可通过session监控文件上传进度

    php.int里配置项:

    session.upoad_progress.enabled             是否启用上传进度报告(默认开启,1开启,0关闭)

    session.upoad_progress.cleanup             是否在上传完成后及时删除进度数据(默认开启,推荐开启)

    session.upload_progress.prefix[=upload_progress_]       进度数据存储位置

    session.upload_progress.freq[=1%]          更新进度的频率(已经处理的字节数),也支持百分比表示%

    session.upload_progress.min_freq[=1.0]   更新进度的时间间隔(秒数)

    开启配置后,可以通过session,来记录一个完整的文件上传进度

    代码推荐网址:http://www.jb51.net/article/56305.htm

    另外,UI使用一些插件上传文件,就可以获取上传进度,不用这么麻烦,例如 Webuploader 

    (拓展)

    ①MIME (Multipurpose Internet Mail Extensions) 多用途Internet邮件扩展,是描述消息内容类型的因特网标准

  • 相关阅读:
    如何在linux系统安装redis
    关于—单例模式
    2.观察者模式(发布-订阅模式)
    1.提供者模式
    提供者模式:提供者的实例化加锁
    为已有的类添加特性,常用于数据库生成的类模型
    C#特性
    JSON.parse(jsonStr)和eval('('+jsonStr+')')
    a标签的href和onclick
    查看SQL语句执行时间/性能测试
  • 原文地址:https://www.cnblogs.com/fightjianxian/p/8594710.html
Copyright © 2011-2022 走看看