• PHP基础之文件的上传与下载


    文件上传与下载

    文件上传

    • 文件上传表单
      • 表单的提交方式必须为POST
      • enctype="multipart/form-data"
        • 说明浏览器可以提供文件上传功能
        • 该属性提示表单中有二进制文件数据
        • <input type="hidden" name="max_file_size" value="30000">
          • 可以指定允许上传文件的最大尺寸
          • MAX_FILE_SIZE必须在文件域的上面。
    <!-- form.html -->
    <form action="upload.php" enctype="multipart/form-data" method="post">
      <input type="hidden" name="max_file_size" value="30000">
      选择文件:<input type="file" name="userfile">
      <input type="submit" value="上传文件">
    </form>
    
    • 文件域 表单的enctype属性

      • 默认情况下,表单传递是字符流,不能传递二进制流
      • 通过设置表单的enctype属性传递复合数据
      • enctype属性的值有
        • application/x-www-form-urlencoded (默认)表示传递的是带格式的文本数据
        • multipart/form-data 复合的表单数据(字符串文件),文件上传必须设置此值
        • text/plain 用于向服务器传递无格式的文本数据,主要用户电子邮件
    • PHP处理上传文件

      • PHP会自动生成一个$_FILES二维数组,该数组保存了上传文件的信息
    # upload.php
    <?php
        $name= $_FILES['userfile']['name'];
        $type= $_FILES['userfile']['type'];
        $size= $_FILES['userfile']['size'];
        $tmpName= $_FILES['userfile']['tmp_name'];
        $error= $_FILES['userfile']['error'];
        echo "{$name}<br>{$type}<br>{$size}<br>{$tmpName}<br>{$error}";
    ?>
    
    • $_FILES['userfile'] 键值说明

      • $_FILES['userfile']['name'] 上传文件的名称
      • $_FILES['userfile']['type'] 上传文件的MIME类型(image/jpeg、image/gif、image/png)
      • $_FILES['userfile']['size'] 上传文件的大小,以字节为单位
      • $_FILES['userfile']['tmp_name'] 文件上传时的临时文件
      • $_FILES[][‘error’] 错误编码(值有0、1、2、3、4、6、7)
        • 0 - 正确
        • 4 - 没有文件上传
        • 1 - 文件大小超过了php.ini中允许的最大值 upload_max_filesize = 2M
        • 2 - 文件大小超过了表单允许的最大值
        • 3 - 只有部分文件上传
        • 6 - 找不到临时文件
        • 7 - 文件写入失败
    • 与文件上传有关的配置

      • post_max_size = 8M 表单允许的最大值
      • upload_max_filesize = 2M 允许上传的文件大小
      • upload_tmp_dir =F:wamp mp 指定临时文件地址,如果不知道操作系统指定
      • file_uploads = On 是否允许文件上传
      • max_file_uploads = 20 允许同时上传20个文件
    <?php
      echo ini_get('post_max_size');
      echo ini_get('upload_max_filesize');
      echo ini_get('upload_tmp_dir');
      echo ini_get('file_uploads');
      echo ini_get('max_file_uploads');
    ?>
    
    • 将上传文件移动到指定位置
      • move_uploaded_file() 临时地址,目标地址
      • 上传的同名的文件要给覆盖
    # upload.php
    <?php
      mkdir('D:Program Filesxampphtdocsuploads');
      $newDir= "uploads/".$_FILES['userfile']['name'];
      if(!empty($_POST)) {
        if($_FILES['userfile']['error']== 0){  
          if(move_uploaded_file($_FILES['userfile']['tmp_name'], $newDir)){
            echo "上传成功";
          };
        }else{
          echo '上传有误';
          echo '错误码:'.$_FILES['userfile']['error'];
          exit;
        }
      }
    ?>
    

    优化文件上传

    • 更改文件名
      • 通过时间戳做文件名
      • 通过uniqid()实现
        • uniqid() 生成唯一的ID
        • uniqid('goods_') 带有前缀
        • uniqid('goods_',true) 唯一ID+随机数
    # upload.php
    <?php
        # 判断是否存在目录
        $dir= 'D:Program Filesxampphtdocsuploads';
        if(!is_dir($dir)){
            mkdir($dir);
        }
        # 通过时间戳做文件名
        $newName= time().rand(100,999).strrchr($_FILES['userfile']['name'],'.'); 
        $newDir= "uploads/".$newName;
        # 上传服务处理
        if(!empty($_POST)) {
            if($_FILES['userfile']['error']== 0){  
                if(move_uploaded_file($_FILES['userfile']['tmp_name'], $newDir)){
                    echo "上传成功";
                };
            }else{
                echo '上传有误';
                echo '错误码:'.$_FILES['userfile']['error'];
                exit;
            }
        }
    ?>
    
    # upload.php
    <?php
        # 判断是否存在目录
        $dir= 'D:Program Filesxampphtdocsuploads';
        if(!is_dir($dir)){
            mkdir($dir);
        }
        # 通过uniqid()实现
        $newName= uniqid('goods_',true).strrchr($_FILES['userfile']['name'],'.'); 
        $newDir= "uploads/".$newName;
        # 上传服务处理
        if(!empty($_POST)) {
            if($_FILES['userfile']['error']== 0){  
                if(move_uploaded_file($_FILES['userfile']['tmp_name'], $newDir)){
                    echo "上传成功";
                };
            }else{
                echo '上传有误';
                echo '错误码:'.$_FILES['userfile']['error'];
                exit;
            }
        }
    ?>
    
    • 验证文件格式
      • 将文件的后缀和允许的后缀对比 (不能识别文件伪装)
      • 通过$_FIELS[]['type']类型判断 (不能识别文件伪装)
      • 在php.ini中开启fileinfo扩展 (可以防止文件伪装)
    # # upload.php
    <?php
      if(!empty($_POST)) {
        # 判断是否存在目录
        $dir= 'D:Program Filesxampphtdocsuploads';
        if(!is_dir($dir)){
          mkdir($dir);
        }
        # 通过uniqid()实现重命名
        $newName= uniqid('goods_',true).strrchr($_FILES['userfile']['name'],'.'); 
        $newDir= "uploads/".$newName;
        # 文件名拓展名验证
        $allow= array('.jpg','.png','.gif');
        $ext= strrchr($_FILES['userfile']['name'],'.');
        if(!in_array($ext,$allow)){
          echo '文件上传不合法';
          exit;
        }
        # 上传服务处理
        if($_FILES['userfile']['error']== 0){  
          if(move_uploaded_file($_FILES['userfile']['tmp_name'], $newDir)){
            echo "上传成功";
          };
        }else{
          echo '上传有误';
          echo '错误码:'.$_FILES['userfile']['error'];
          exit;
        }
      }
    ?>
    
    # upload.php
    <?php
      if(!empty($_POST)) {
        # 判断是否存在目录
        $dir= 'D:Program Filesxampphtdocsuploads';
        if(!is_dir($dir)){
          mkdir($dir);
        }
        # 通过uniqid()实现重命名
        $newName= uniqid('goods_',true).strrchr($_FILES['userfile']['name'],'.'); 
        $newDir= "uploads/".$newName;
        # 文件名拓展名验证
        $allow= array('image/jpeg','image/png','image/gif');
        $ext= $_FILES['userfile']['type'];
        if(!in_array($ext,$allow)){
          echo '文件上传不合法';
          exit;
        }
        # 上传服务处理
        if($_FILES['userfile']['error']== 0){  
          if(move_uploaded_file($_FILES['userfile']['tmp_name'], $newDir)){
            echo "上传成功";
          };
        }else{
          echo '上传有误';
          echo '错误码:'.$_FILES['userfile']['error'];
          exit;
        }
      }
    ?>
    
    # upload.php
    <?php
      if(!empty($_POST)) {
        # 判断是否存在目录
        $dir= 'D:Program Filesxampphtdocsuploads';
        if(!is_dir($dir)){
          mkdir($dir);
        }
        # 通过uniqid()实现重命名
        $newName= uniqid('goods_',true).strrchr($_FILES['userfile']['name'],'.'); 
        $newDir= "uploads/".$newName;
        # 文件名拓展名验证
        $info=finfo_open(FILEINFO_MIME_TYPE);
        $ext= finfo_file($info, $_FILES['userfile']['tmp_name']);
        $allow= array('image/jpeg','image/png','image/gif');
        if(!in_array($ext,$allow)){
          echo '文件上传不合法';
          exit;
        }
        # 上传服务处理
        if($_FILES['userfile']['error']== 0){  
          if(move_uploaded_file($_FILES['userfile']['tmp_name'], $newDir)){
            echo "上传成功";
          };
        }else{
          echo '上传有误';
          echo '错误码:'.$_FILES['userfile']['error'];
          exit;
        }
      }
    ?>
    
    • 优化文件上传
    <?php
        if(!empty($_POST)) {
            # 判断是否存在目录
            $dir= 'D:Program Filesxampphtdocsuploads';
            if(!is_dir($dir)){
                mkdir($dir);
            }
            # 通过uniqid()实现重命名
            $newName= uniqid('goods_',true).strrchr($_FILES['userfile']['name'],'.'); 
            $newDir= "uploads/".$newName;
            # 文件名拓展名验证
            $info=finfo_open(FILEINFO_MIME_TYPE);
            $ext= finfo_file($info, $_FILES['userfile']['tmp_name']);
            $allow= array('image/jpeg','image/png','image/gif');
            if(!in_array($ext,$allow)){
                echo '只能上传 '.implode(' , ',$allow).' 等文件格式';
                exit;
            }
            # 验证文件大小
            $fileSize= ini_get('upload_max_filesize');
            if(substr($fileSize, -1, 1)== 'k'){
                $fileSize= (integer)$fileSize* 1024;
            }elseif(substr($fileSize, -1, 1)== 'M'){
                $fileSize= (integer)$fileSize* 1024* 1024;
            }elseif(substr($fileSize, -1, 1)== 'G'){
                $fileSize= (integer)$fileSize* 1024* 1024* 1024;
            }elseif(substr($fileSize, -1, 1)== 'T'){
                $fileSize= (integer)$fileSize* 1024* 1024* 1024* 1024;
            }
            if($_FILES['userfile']['size']> $fileSize){
                echo '文件大小不能超过'.number_format($fileSize/1024, 1).'K';
                exit;
            }
            # 验证是否是http上传
            if(!is_uploaded_file($_FILES['userfile']['tmp_name'])){
                echo '文件不是HTTP POST上传的<br>';
                exit;
            }
            # 上传服务处理
            if($_FILES['userfile']['error']== 0){  
                if(move_uploaded_file($_FILES['userfile']['tmp_name'], $newDir)){
                    echo "上传成功";
                };
            }else{
                switch($_FILES['userfile']['error']) {
                    case 1:
                        echo '文件大小超过了php.ini中允许的最大值,最大值是:'.ini_get('upload_max_filesize');
                        break;  
                    case 2:
                        echo '文件大小超过了表单允许的最大值';
                        break; 
                    case 3:
                        echo '只有部分文件上传';
                        break; 
                    case 4:
                        echo '没有文件上传';
                        break; 
                    case 6:
                        echo '找不到临时文件';
                        break; 
                    case 7:
                        echo '文件写入失败';
                        break; 
                    default:
                        echo '未知错误';
                        break; 
                }
            }
        }
    ?>
    

    文件下载

    • 方法解释

      • __FILE__ 当前文件的带文件名的绝对路径
      • dirname(__FILE__) 返回路径中的目录部分
      • iconv() 文件编码转换
      • feof() 检测流上的文件结束符的函数,如果文件结束,则返回非0值,否则返回0
    • 响应头设置

      • Content-type: application/octet-stream 指定文件类型
      • Content-Disposition: attachment; filename={$file_name} 指定文件描述
    <?php
        header('Content-Type:text/html; charset=utf-8');
        define('ROOT_PATH', dirname(__FILE__));
    
        function downfile($file_path){
            $file_path= iconv('utf-8', 'gb2312', $file_path);
            if(!file_exists($file_path)){
                exit('文件不存在!');
            }
    
            $file_name= basename($file_path);
            $file_size= filesize($file_path);
            $file= fopen($file_path, 'r');
            header("Content-type: application/octet-stream");
            header("Content-Disposition: attachment; filename={$file_name}");
    
            $buffer= 1024;
            $file_count= 0;
    
            while(!feof($file) && ($file_size- $file_count> 0)){
                $file_data= fread($file, $buffer);
                $file_count+= $buffer;
                echo $file_data;
            }
    
            fclose($file);
        }
        downfile(ROOT_PATH.".imgpigger.jpg");
    ?>
    
  • 相关阅读:
    转--Android中自定义字体的实现方法
    android中Intent传值与Bundle传值的区别详解
    通过Application传递数据代码
    LayoutInflater的使用
    转--Android资源总结(环境搭建/ 反编译工具)
    转--android Toast大全(五种情形)建立属于你自己的Toast
    转--9中对话框
    转--全局异常处理
    安卓记住密码
    转--Android学习笔记-实用代码合集
  • 原文地址:https://www.cnblogs.com/SharkJiao/p/14023629.html
Copyright © 2020-2023  润新知