• PHP12 文件操作


    学习要点

    • 文件系统概述
    • 目录基本操作
    • 文件基本操作
    • 文件上传下载
    • 文件上传类的设计

     

     

    文件系统概述

    概述

    PHP文件系统的操作是基于UNIX系统模型,所以有一些文件处理函数无法在windows服务器中使用。绝大部分文件处理函数兼容windows操作系统和UNIX系统。

    文件类型

    Windows:file,dir,unknown;

    Unix:block(磁盘分区、光驱等),char(键盘、打印机等),fifo(命名管道,进程间信息传递),link(类似快捷方式),file,dir,unknown

    • 文件类型判断filetype()函数

    语法格式:string filetype ( string $filename )

    参数:文件路径

    返回值:正常返回文件类型,异常返回false。

        示例:

    echo filetype('c:\windows');//dir
    
    echo filetype('c:\jtts4_sapi5.log');//file
    
    echo filetype('c:/jtts4_sapi5.log');//file
    
     
    
    //判断是否是文件
    
    var_dump(is_file('c:/jtts4_sapi5.log'));
    
    //判断是否是目录(文件夹)
    
    var_dump(is_dir('c:/jtts4_sapi5.log'));
    
    • file_exists():判断文件是否存在
    • is_readable():判断文件是否可读
    • is_writable():判断文件是否可写
    • is_executable():判断文件是否可执行
    • filectime():获取文件创建时间
    • filemtime():获取文件编辑时间
    • fileatime():获取文件最后打开时间

    文件的属性

    示例1:D02FileProperty.php

    <?php
    
    /**
     * 判断文件类型
     * @param $fileName  文件路径
     * @return string  文件的类型
     */
    function getFileType($fileName)
    {
        $type = "";//文件类型
        switch (filetype($fileName)) {
            case "file":
                $type = "普通文件";
                break;
            case "dir":
                $type = "目录";
                break;
            case "block":
                $type = "块设备文件";
                break;
            case "char":
                $type = "字符设备文件";
                break;
            case "fifo":
                $type = "命名管道文件";
                break;
            case "link":
                $type = "符号链接文件";
                break;
            default:
                $type = "未知文件";
                break;
        }
        return $type;
    }
    
    
    /**
     * 读取文件的属性
     * @param $fileName 文件路径
     */
    function getFileProperty($fileName)
    {
        //判断文件是否存在
        if (!file_exists($fileName)) {
            echo "目标文件不存在!
    ";
            return;
        }
    
        //判断是文件还是目录
        if (is_file($fileName)) {
            echo $fileName . "是一个普通文件。
    ";
        }
    
        if (is_dir($fileName)) {
            echo $fileName . "是一个目录。
    ";
        }
    
        //获取文件类型
        echo "文件类型:" . getFileType($fileName) . "
    ";
    
        //获得文件的大小
        echo "文件的大小:" . getFileSize(filesize($fileName)) . "
    ";
    
        //判断文件的读、写、可执行的属性
        if (is_readable($fileName)) {
            echo "文件是可读的。
    ";
        }
        if (is_writable($fileName)) {
            echo "文件是可写的。
    ";
        }
        if (is_executable($fileName)) {
            echo "文件是可执行的。
    ";
        }
    
        //文件的创建时间
        echo "文件的创建时间" . date("Y-m-d H:i:s", filectime($fileName)) . "
    ";
        //文件的编辑时间
        echo "文件的编辑时间" . date("Y-m-d H:i:s", filemtime($fileName)) . "
    ";
        //文件最后打开的时间
        echo "文件最后打开的时间" . date("Y-m-d H:i:s", fileatime($fileName)) . "
    ";
    }
    
    /**
     * 文件大小换算
     * @param $bytes 文件字节数
     * @return string 文件大小和单位
     */
    function getFileSize($bytes)
    {
        /*
        *pow(number $base , number $exp)指数表达式
         *round(float $val [, int $precision = 0 [, int $mode = PHP_ROUND_HALF_UP ]] ) 对浮点数进行四舍五入
         *1T=1024G
         *1G=1024M
         *1M=1024KB  //1byte=8bit   11110001
         *1K=1024B
         */
        $size = 0;
        if ($bytes >= pow(2, 40)) {
            $size = round($bytes / pow(1024, 4), 2);//四舍五入,小数点后保留2位
            $subfix = "TB";
        } elseif ($bytes >= pow(2, 30)) {
            $size = round($bytes / pow(1024, 3), 2);
            $subfix = "GB";
        } elseif ($bytes >= pow(2, 20)) {
            $size = round($bytes / pow(1024, 2), 2);
            $subfix = "MB";
        } elseif ($bytes >= pow(2, 10)) {
            $size = round($bytes / pow(1024, 1), 2);
            $subfix = "KB";
        } else {
            $size = $bytes;
            $subfix = "Byte";
        }
        return $size . "" . $subfix;
    }
    
    $fileName = "media.wmv";
    
    getFileProperty($fileName);
    

      

    清除文件缓存

    以下函数,PHP将缓存信息
    stat(), lstat(), file_exists(), is_writable(),
    is_readable(), is_executable(), is_file(),
    is_dir(), is_link(), filectime(), fileatime(),
    filemtime(), fileinode(), filegroup(), fileowner(), filesize(), filetype() 和 fileperms()。


    如果需要清除缓存,使用以下函数:
    void clearstatcache ([ bool $clear_realpath_cache = false [, string $filename ]] )

    作用:清除文件状态缓存

    参数:clear_realpath_cache————是否清除真实路径缓存

    参数:filename————清除文件名指定的文件的真实路径缓存; 只在 clear_realpath_cache 为 TRUE 时启用
     

    示例2:D02FilePropertyStat.php

    $filePro = stat('media.wmv');
    //var_dump($filePro);
    print_r(array_slice($filePro, 13));//从数组13个元素开始输出
    clearstatcache(true,'media.wmv');//清除缓存信息
    //clearstatcache();//清除脚本中的所有缓存
    

      

    目录基本操作

    目录路径解析

    • 绝对路径

    Windows系统路径分隔符: \  和 /

    Unix系统路径分隔符:/

    • 相对路径

    ../ 上一级目录

    ./   当前目录

    • 各种系统默认路径分隔符

    PHP内置常量:DIRECTORY_SEPARATOR

    • 读取路径中各部分属性

    basename():返回文件名

    dirname():返回目录

    pathinfo():返回路径关联数组

     示例代码

    <?php
    $fileName1='testdir/t1.txt';
    $fileName2='testdir'.DIRECTORY_SEPARATOR.'t1.txt';
    
    echo filetype($fileName2);
    
    /**
     * string basename ( string $path [, string $suffix ] )
     * 给出一个包含有指向一个文件的全路径的字符串,本函数返回基本的文件名
     * suffix:如果文件名是以 suffix 结束的,那这一部分也会被去掉。
     */
    echo basename($fileName1);//返回t1.txt
    echo basename($fileName1,'.txt');//返回t1
    
    
    /**
     * string dirname ( string $path )
     * 给出一个包含有指向一个文件的全路径的字符串,本函数返回去掉文件名后的目录名。
     */
    echo dirname($fileName2);//输出testdir
    echo dirname("c:/");//输出c:/
    echo dirname("c:/abc.txt");//输出c:/
    
    /**
     * mixed pathinfo ( string $path [, int $options = PATHINFO_DIRNAME | PATHINFO_BASENAME | PATHINFO_EXTENSION | PATHINFO_FILENAME ] )
     * 返回一个关联数组包含有 path 的信息。返回关联数组还是字符串取决于 options。
     * 参数:
     * path
     * 要解析的路径。
     * options
     * 如果指定了,将会返回指定元素;它们包括:PATHINFO_DIRNAME,PATHINFO_BASENAME 和 PATHINFO_EXTENSION 或 PATHINFO_FILENAME。
     * 如果没有指定 options 默认是返回全部的单元。
     */
    $path_part=pathinfo($fileName1);
    var_dump($path_part);//输出全部信息
    echo $path_part['dirname'];//输出testdir
    

      

    遍历目录

    • opendir():打开一个目录句柄,可用于之后的 closedir(),readdir() 和 rewinddir() 调用中。
    • readdir():返回目录中下一个文件的文件名。文件名以在文件系统中的排序返回。
    • closedir():关闭由 dir_handle 指定的目录流。流必须之前被 opendir() 所打开。
    • rewinddir():将 dir_handle 指定的目录流重置到目录的开头。
    • 示例代码如下:
    include "util.php";
    //遍历c:windows目录
    $fileName = "c:/windows";
    $dirHandler = opendir($fileName);//1.创建一个目录句柄
    //$file=readdir($dirHandler);//2.读一个文件
    
    echo "<table border='1px' width='600px' align='center'>";
    echo "<caption><h2>" . $fileName . "下的文件信息</h2></caption>";
    echo "<tr><th>文件名</th><th>文件类型</th><th>文件大小</th><th>文件修改日期</th></tr>";
    
    $count = 0;//统计有多少个文件
    
    while ($file = readdir($dirHandler)) {//2.遍历每个文件
        $count++;
        //构建目录下文件或者目录的路径
        $filePath = $fileName . DIRECTORY_SEPARATOR . $file;
        //隔行变色
        if ($count % 2 == 1) {
            echo "<tr style='background: #ccc'>";
        } else {
            echo "<tr>";
        }
        echo "<td>" . $file . "</td>";//文件名
        //文件类型
        if(filetype($filePath)=="dir"){
            echo "<td>文件夹</td>";
        }else if(filetype($filePath)=="file"){
            echo "<td>文件</td>";
        }else{
            echo "<td>未知文件类型</td>";
        }
        echo "<td>" . getFileSize(filesize($filePath)) . "</td>";//文件大小
        echo "<td>" . date("Y-m-d H:i:s", filemtime($filePath)) . "</td>";//文件修改日期
        echo "</tr>";
    
    }
    echo "<tr><td colspan='4'>" . $fileName . "目录下文件数量:" . $count . "</td></tr>";
    echo "</table>";
    
    closedir($dirHandler);//3.关闭目录句柄
    

      

    统计目录大小

    • 设计递归函数统计目录大小
    • filesize()函数
    • 示例代码
    <?php
    //统计目录大小
    include "util.php";
    //遍历c:windows目录
    $fileName = "c:/windows";
    
    /**
     * 统计目录大小
     * @param $dir 目录路径
     * @return int 以字节为单位的目录的大小
     */
    function countDirSize($dir)
    {
        $size = 0;//目录大小
        if ($dirHandler = opendir($dir)) {//1.创建一个目录句柄,成功打开目录句柄
            while ($file = readdir($dirHandler)) {//2.遍历每个文件
                //去掉.和..
                if ($file != "." && $file != "..") {
                    //构建目录下文件或者目录的路径
                    $filePath = $dir . DIRECTORY_SEPARATOR . $file;
                    //判断是文件还是目录
                    if(is_file($filePath)){//文件
                        $size+=filesize($filePath);
                    }
                    if(is_dir($filePath)){//目录
                        $size+= countDirSize($filePath);//递归调用
                    }
                }
            }
            //3.关闭目录资源
            closedir($dirHandler);
        }
        return $size;
    }
    
    $dir="c:/windows";
    echo "开始时间".date("Y-m-d H-i-s",time())."
    ";
    echo  getFileSize(countDirSize($dir));
    echo "
    结束时间".date("Y-m-d H-i-s",time());
    

      

    创建和删除目录

    • mkdir():创建新目录
    • rmdir():只能删除空目录
    • unlink():删除文件
    /**建立目录*/
    
    mkdir("mkdemo");
    
    /**创建一个文件*/
    
    fopen("mkdemo/test.txt", 'w+');
    
    /**删除文件*/
    
    unlink("mkdemo/test.txt");
    
    /**删除空目录*/
    
    rmdir("mkdemo");
    
    • 递归删除目录函数的设计
    //设计删除目录的函数
    function delDir($dir){
        //判断目录是否存在
        if(file_exists($dir)){//目录存在
            //清空目录和子目录内的文件
            if ($dirHandler = opendir($dir)) {//1.创建一个目录句柄,成功打开目录句柄
                while ($file = readdir($dirHandler)) {//2.遍历每个文件
                    //去掉.和..
                    if ($file != "." && $file != "..") {
                        //构建目录下文件或者目录的路径
                        $filePath = $dir . DIRECTORY_SEPARATOR . $file;
                        //判断是文件还是目录
                        if(is_file($filePath)){//文件
                            unlink($filePath);//删除文件
                        }
                        if(is_dir($filePath)){//目录
                            delDir($filePath);//递归调用
                        }
                    }
                }
            }
            //删除目录
            rmdir($dir);
            //3.关闭目录资源
            closedir($dirHandler);
        }
    }
    

      

    复制目录

    Php只提供了复制文件的函数copy(),二没有提供复制目录的函数。需要自定义。

    递归复制目录示例代码:

    //copy("test","test2");//只能拷贝文件
    copy("testdir", "testdir2");//无法拷贝目录
    
    //设计递归拷贝目录
    function copyDir($srcDir, $destDir)
    {
    
        //判断目标路径是否是一个文件
        if (is_file($destDir)) {
            //die("目标路径不是一个目录!");
            echo "目标路径不是一个目录!";
            return;
        }
    
        //判断目标目录是否存在,不存在则创建目录
        if (!file_exists($destDir)) {
            mkdir($destDir);//创建目标目录
            //echo "创建目标路径成功!
    ";
        }
    
        //目录拷贝工作
        if ($dirHandler = opendir($srcDir)) {//创建源目录的句柄
            while ($file = readdir($dirHandler)) {//2.遍历每个文件
                //去掉.和..
                if ($file != "." && $file != "..") {
                    //构建目录下文件或者目录的路径
                    $srcFilePath = $srcDir . DIRECTORY_SEPARATOR . $file;//源目录中文件名
                    $destFilePath = $destDir . DIRECTORY_SEPARATOR . $file;//目标目录中文件名
                    //判断是文件还是目录
                    if (is_file($srcFilePath)) {//文件
                        copy($srcFilePath,$destFilePath);//拷贝文件
                    }
                    if (is_dir($srcFilePath)) {//目录
                        copyDir($srcFilePath,$destFilePath);//递归调用
                    }
                }
            }
            closedir($dirHandler);//关闭资源
    
        }
    }
    
    copyDir("testdir", "testdir2");
    

      

    文件基本操作

    文件的打开与关闭

    • resource fopen ( string $filename , string $mode [, bool $use_include_path = false [, resource $context ]] )

        用法: 将 filename 指定的名字资源绑定到一个流上。

                  第一个参数$filename表示要被打开文件的URL。可以是服务器中的绝对路径、相对路径,或者网络资源文件。

                  第二个参数表示文件模式,值如下表所示:

         

    • bool fclose ( resource $handle )

        用法:将 handle 指向的文件关闭。

     

    写入文件

    • 写入文件换行

    UNIX: 

    WIN:  

    Mac:  

    • fwrite()

    int fwrite ( resource $handle , string $string [, int $length ] )

    说明:把 string 的内容写入 文件指针 handle 处。

    写入文件顺序:fopen()  >>>  fwrite()  >>>  fclose()

    • fputs() == fwrite() 
    • file_put_contents($filename ,$data):集成了文件写入顺序操作。
    • 写入文件示例代码
    $file="data.txt";
    //打开文件
    $fileHandler=fopen($file,"w") or die("打开文件失败");
    //写入数据
    for($i=1;$i<100;$i++){
        fwrite($fileHandler,"写入了第{$i}行数据!
    ",4096);
    }
    //fwrite($fileHandler,"世界杯2018!",4096);//第三个参数表示一次写入的字节数,使用4096提高硬盘的IO效率
    //关闭文件
    fclose($fileHandler);
    

      

     

    读取文件内容

    • fread()

    string fread ( resource $handle , int $length )

    说明:fread() 从文件指针 handle 读取最多 length 个字节。

    注意:如果指定读取二进制,在fopen函数中需要指定模式‘b’

    • fgets()、fgetc():每次读取一行、读取一个字符
    • feof():判断是否已经达到文件末尾
    • file():将文件读入到一个数字,每个元素是文件行+换行符。
    • readfile():读取指定整个文件
    • 读取文件示例代码
    $file="data.txt";
    //打开文件
    $fileHandler=fopen($file,"r") or die("打开文件失败");
    //echo fread($fileHandler,4096);
    echo  fread($fileHandler,filesize($file));
    //关闭文件
    fclose($fileHandler);
    
    /*
    *读取一行文件
    */
    $file = "data.txt";
    //打开文件
    $fileHandler = fopen($file, "r") or die("打开文件失败");
    //feof()//判断是否到达文件的末尾
    while (!feof($fileHandler)) {
        echo fgets($fileHandler);
    }
    //关闭文件
    fclose($fileHandler);
    

      

    上机练习1:文件的基本读写操作

      1.使用fwrite循环写入10行数据,要求换行。

      2.使用fgets循环读出数据,按行读取。

      3.读写功能封装为函数

    读取二进制文件

    • windows系统中区分二进制文件和文本文件
    • unix系统中不区分
    • 读取二进制文件的打开模式需要添加“b”模式
    • 示例的代码:读取图像文件并输出到网页
    header('Content:image/jpg');
    $file="bird.jpg";
    //打开文件
    //windows系统区分二进制文件和文本文件,unix不区分
    $fileHandler=fopen($file,"rb") or die("打开文件失败");
    
    $content="";
    while (!feof($fileHandler)){
        $content.=fread($fileHandler,4096);
    }
    //关闭文件
    fclose($fileHandler);
    echo $content;
    

      

    访问远程文件

    • 使用方式与本地函数相同
    • 需要在php.ini中打开allow_url_fopen
    • 超时限定函数:set_time_limit($seconds)
    • http协议只读;ftp协议看服务器是否支持写
    • 示例代码:读取网页中<h1>标签中的信息
    //打开文件
    $fileHandler=fopen("https://www.cnblogs.com/rask/p/9016386.html","r") or die("打开文件失败");
    while (!feof($fileHandler)){
        $line=fgets($fileHandler,4096);
        if(preg_match("/<h1>(.*)</h1>/",$line,$out)){//()子模式
            echo $out[1];
            print_r($out);
            break;
        }
    }
    //关闭文件
    fclose($fileHandler);
    

       

    上机练习2:二进制文件的读取

    需求描述:读取硬盘上的图片,显示在网页上

    上机练习3:http网页的读取

    需求描述:

    1.读取http页面
    2.解析<h1>标签内容

    移动文件指针

    • 文件指针度量单位:字节
    • int ftell ( resource $handle )

        说明:返回由 handle 指定的文件指针的位置,也就是文件流中的偏移量

    • int fseek ( resource $handle , int $offset [, int $whence = SEEK_SET ] )

    说明:在与 handle 关联的文件中设定文件指针位置。 新位置从文件头开始以字节数度量,是以 whence 指定的位置加上 offset。

    SEEK_SET - 设定位置等于 offset 字节。

    SEEK_CUR - 设定位置为当前位置加上 offset。

    SEEK_END - 设定位置为文件尾加上 offset(负数)。

    • bool rewind ( resource $handle )

    说明:将 handle 的文件位置指针设为文件流的开头。 

    • 示例代码
    $fp = fopen ( 'DirDemo/demo.txt', 'r' ) or die ( "文件打开失败" ); // 以只读模式打开文件
    //echo ftell ( $fp ) . "<br>"; // 输出刚打开文件的指针默认位置,指针在文件的开头位置为0
    echo fread ( $fp, 10 ) . "<br>"; // 读取文件中的前10个字符输出,指针位置发生了变化
    echo ftell ( $fp ) . "<br>"; // 读取文件的前10个字符之后,指针移动的位置在第10个字节处
    fseek ( $fp, 100, SEEK_CUR ); // 将文件指针的位置,由当前位置向后移动100个字节数
    echo ftell ( $fp ) . "<br>"; // 文件位置在110个字节处
    echo fread ( $fp, 10 ) . "<br>"; // 读取110到120字节数位置的字符串,读取后指针的位置为120
    //echo ftell ( $fp );
    fseek ( $fp, - 10, SEEK_END ); // 又将指针移动到倒数10个字节位置处
    echo ftell ( $fp ). "<br>";
    //echo fread ( $fp, 10 ) . "<br>"; // 输出文件中最后10个字符
    rewind ( $fp ); // 又移动文件指针到文件的开头
    echo ftell ( $fp ) . "<br>"; // 指针在文件的开头位置,输出0
    fclose ( $fp );                	//关闭文件资源
    

      

    文件锁定机制

    bool flock ( resource $handle , int $operation [, int &$wouldblock ] )
    

      

    说明:flock() 允许执行一个简单的可以在任何平台中使用的读取/写入模型(包括大部分的 Unix 派生版和甚至是 Windows)。

    在 PHP 5.3.2版本之前,锁也会被 fclose() 释放(在脚本结束后会自动调用)。

    PHP 支持以咨询方式(也就是说所有访问程序必须使用同一方式锁定, 否则它不会工作)锁定全部文件的一种轻便方法。 默认情况下,这个函数会阻塞到获取锁;这可以通过下面文档中 LOCK_NB 选项来控制(在非 Windows 平台上)。

    留言板关键示例代码

    	<?php
    		//error_reporting(0);
    		// 数据保存文件
    		$filename = "DirDemo/text_data.txt";
    		
    		// 接收表单中三条内容,并整合为一条,使用“||”分隔,使用“<|>”结尾
    		if (isset ( $_POST ["sub"] )) {
    			$message = $_POST ["username"] . "||" . $_POST ["title"] . "||" . $_POST ["mess"] . "<|>";
    			writeMessage ( $filename, $message ); // 调用自定义函数,将信息写入文件
    		}
    		
    		// 判断文件是否存在,如果存在则条件成立
    		if (file_exists ( $filename )) {
    			// 文件存在则调用自定义函数,读取数据
    			readMessage ( $filename ); 
    		}
    		
    		/**
    		 * 写消息
    		 * @param string $filename 文件路径
    		 * @param string $message 待写入消息
    		 */
    		function writeMessage($filename, $message) { 
    			$fp = fopen ( $filename, "a" ); // 以追加模式打开文件
    			if (flock ( $fp, LOCK_EX )) { // 进行排它型锁定(独占锁定)
    				fwrite ( $fp, $message ); // 将数据写入文件
    				flock ( $fp, LOCK_UN ); // 同样使用flock()函数释放锁定
    			} else { // 如果建立独占锁定失败
    				echo "不能锁定文件!"; // 输出错误消息
    			}
    			fclose ( $fp ); // 关闭文件资源
    		}
    		
    		/**
    		 * 读取消息
    		 * @param string $filename 文件路径
    		 */
    		function readMessage($filename) {
    			$fp = fopen ( $filename, "r" ); // 以只读的模式打开文件
    			flock ( $fp, LOCK_SH ); // 建立文件的共享锁定
    			$buffer = ""; // 将文件中的数据遍历后放入这个字符串中
    			while ( ! feof ( $fp ) ) { // 使用while循环将文件中数据遍历出来
    				$buffer .= fread ( $fp, 1024 ); // 读出数据追加到$buffer变量中
    			}
    			$data = explode ( "<|>", $buffer ); // 通过“<|>”将每行留言分隔并存入到数组中
    
    			foreach ( $data as $line ) { // 遍历数组将每行数据以HTML输出
    				if($line==null) break;
    				list ( $username, $title, $message ) = explode ( "||", $line ); // 将每行数据再分隔
    				if ($username != "" && $title != "" && $message != "") { // 判断每部分是否为空
    					echo $username . '说:'; // 输出用户名
    					echo ' ' . $title . ','; // 输出标题
    					echo $message . "<hr>"; // 输出留言主题信息
    				}
    			}
    			
    			flock ( $fp, LOCK_UN ); // 释放锁定
    			fclose ( $fp ); // 关闭文件资源
    		}
    		?>
    

      

     

    文件基本操作函数

    • copy( )

        bool copy ( string $source , string $dest [, resource $context ] )

        用法:将文件从 source 拷贝到 dest。

    • unlink( )

        bool unlink ( string $filename [, resource $context ] )

        用法:删除 filename。和 Unix C 的 unlink() 函数相似。 发生错误时会产生一个 E_WARNING 级别的错误。

    • ftruncate()

        bool ftruncate ( resource $handle , int $size )

        用法:接受文件指针 handle 作为参数,并将文件大小截取为 size。

    • rename()

        bool rename ( string $oldname , string $newname [, resource $context ] )

        用法:尝试把 oldname 重命名为 newname。

    • 示例代码
    <?php
    if (copy ( './file1.txt', '../data/file2.txt' )) { // 复制文件示例
    	echo "文件复制成功!";
    } else {
    	echo "文件复制失败!";
    }
    
    $filename = "file1.txt"; // 删除文件示例
    if (file_exists ( $filename )) {
    	if (unlink ( $filename )) {
    		echo "文件删除成功!";
    	} else {
    		echo "文件删除失败!";
    	}
    } else {
    	echo "目标文件不存在";
    }
    
    if (rename ( './demo.php', './demo.html' )) { // 重命名文件示例
    	echo "文件重命名成功!";
    } else {
    	echo "文件重命名失败";
    }
    
    $fp = fopen ( './data.txt', "r+" ) or die ( '文件打开失败' ); // 截取文件示例
    if (ftruncate ( $fp, 1024 )) {
    	echo "文件截取成功!";
    } else {
    	echo "文件截取失败!";
    }
    

      

     

    文件上传

    • 客户端设置

       1、设置表单数据编码格式

    enctype="multipart/form-data"
    

      

      2、设置表单的数据传输方法

    method="post"
    

      

      3、设置隐藏域,提示用户上传文件大小限制

    <input type="hidden" name="MAX_FILE_SIZE" value="1000000"> 
    

      

    •  服务器端处理上传文件

    php.ini的配置

    file_uploads:on

    upload_max_filesize:2M

    post_max_size:8M

    upload_tmp_dir:null

    • 使用全局数组$_FILES接收文件 

    以我们假设文件上传字段的名称为 myfile:

      $_FILES['myfile']['name']:客户端上传的文件的原名称。

      $_FILES['myfile']['type']:文件的 MIME 类型。

      $_FILES['myfile']['size']:已上传文件的大小,单位为字节。

      $_FILES['myfile']['tmp_name']:文件被上传后在服务端储存的临时文件名。

      $_FILES['myfile']['error']:和该文件上传相关的错误代码。

     

    • 错误代码

    $_FILES['img']['error']有以下几种类型
    UPLOAD_ERR_OK:其值为 0,没有错误发生,文件上传成功。
    UPLOAD_ERR_INI_SIZE:其值为 1,上传的文件超过了 php.ini 中 upload_max_filesize选项限制的值。
    UPLOAD_ERR_FORM_SIZE:其值为 2,上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。
    UPLOAD_ERR_PARTIAL:其值为 3,文件只有部分被上传。
    UPLOAD_ERR_NO_FILE:其值为 4,没有文件被上传。
    UPLOAD_ERR_NO_TMP_DIR:其值为 6,找不到临时文件夹。PHP 4.3.10 和 PHP 5.0.3 引进。
    UPLOAD_ERR_CANT_WRITE:其值为 7,文件写入失败。PHP 5.1.0 引进。

     

    • 从临时目录读取上传文件

    is_upload_file():判断是否为上传文件

    move_uploaded_file():从临时空间转移到指定位置

    • 参考示例代码
    // error_reporting(0);
    
    // $des=$_POST['description'];
    // echo '照片描述:'.$des;
    
    // var_dump($_FILES['myfile']);
    
    $allowtype = array (
    		"gif",
    		"png",
    		"jpg",
    		"jpeg"
    ); // 设置充许上传的类型为gif, png, jpg,jpeg
    
    $size = 1000000; // 设置充许大小为1M(1000000字节)以内的文件
    $path = "./uploads"; // 设置上传后保存文件的路径,指定当前目录下的uploads目录
    
    
    /* 判断文件是否可以成功上传到服务器,$_FILES['myfile']['error']值为0表示上传成功 ,其它值则出错 */
    if ($_FILES ['myfile'] ['error'] > 0) {
    	echo '上传错误: ';
    	switch ($_FILES ['myfile'] ['error']) {
    		case 1 :
    			die ( '上传文件大小超出了PHP配置文件中的约定值:upload_max_filesize' );
    		case 2 :
    			die ( '上传文件大小超出了表单中的约定值:MAX_FILE_SIZE' );
    		case 3 :
    			die ( '文件只被部分上载' );
    		case 4 :
    			die ( '没有上传任何文件' );
    		default :
    			die ( '未知错误' );
    	}
    }
    
    /* 判断上传的文件是否为充许的文件类型 */
    //文件名转数组,第一个元素文件名,第二个元素扩展名
    $fileNameArray=explode ( ".", $_FILES ['myfile'] ['name'] );
    //输出文件名数组最后一个元素
    $hz = array_pop ( $fileNameArray ); 
    /* 通过判断文件的后缀方式,来决定文件是否是充许上传的文件类型 */
    if (! in_array ( $hz, $allowtype )) {
    	die ( "这个后缀是<b>" . $hz . "</b>, 不是充许的文件类型!" );
    }
    
    /*
     * 也可以通过获取上传文件的MIME类型中的主类型和子类型,来限制文件上传的类型
     * list($maintype,$subtype)=explode("/",$_FILES['myfile']['type']);
     * if ($maintype=="text") { //通过主类型限制不能上传文本文件,例如.txt .html .php等文件
     * die('问题: 不能上传文本文件。'); //如果用户上传文本文件则退出程序
     * }
     */
    
    /* 判断上传的文件是否为充许尺寸范围内 */
    if ($_FILES ['myfile'] ["size"] > $size) {
    	die ( "超过了充许的<b>{$size}<b>字节大小!" );
    }
    
    /* 为了系统安全,也为了同名文件会被覆盖,上传后将文件名使用系统定义 */
    $filename = date ( "YmdHis" ) . rand ( 100, 999 ) . "." . $hz;
    
    /* 判断是否为上传文件 */
    if (is_uploaded_file ( $_FILES ['myfile'] ['tmp_name'] )) {
    	// 移动文件:从临时空间转移到目标位置
    	if (! move_uploaded_file ( $_FILES ['myfile'] ["tmp_name"], $path . '/' . $filename )) { 
    		die ( '问题: 不能将文件移动到指定目录。' );
    	}
    } else {
    	die ( "问题: 上传文件{$_FILES['myfile']['name']}不是一个合法文件!" );
    }
    
    
    /* 如果文件上传成功则输出 */
    echo "文件{$filename}上传成功,保存在目录{$path}中,大小为{$_FILES['myfile']['size']}字节";
    
    • 多文件上传示例:

         客户端代码:

    <!--客户端的设置-->
    <form action="action.php" enctype="multipart/form-data" method="post">
        <!--设定隐藏域-->
        <input type="hidden" name="MAX_FILE_SIZE" value="1000000">
        <p>请选择要上传的文件:<input type="file" name="myfile[]"></p>
        <p>请选择要上传的文件:<input type="file" name="myfile[]"></p>
        <p>请选择要上传的文件:<input type="file" name="myfile[]"></p>
        <p>请选择要上传的文件:<input type="file" name="myfile[]"></p>
        <p>请选择要上传的文件:<input type="file" name="myfile[]"></p>
        <p><input type="submit" name="sub" value="上传"></p>
    </form>
    

      

             服务器端代码:

    $allowtype = array(
        "gif",
        "png",
        "jpg",
        "jpeg"
    ); // 设置充许上传的类型为gif, png, jpg,jpeg
    $size = 1000000; // 设置充许大小为1M(1000000字节)以内的文件
    $path = "./uploads"; // 设置上传后保存文件的路径,指定当前目录下的uploads目录
    
    for ($i = 0; $i < count($_FILES["myfile"]["error"]); $i++) {
        /* 判断文件是否可以成功上传到服务器,$_FILES['myfile']['error']值为0表示上传成功 ,其它值则出错 */
        if ($_FILES["myfile"]["error"][$i] > 0) {
            echo '上传错误: ';
            switch ($_FILES ['myfile'] ['error']) {
                case 1 :
                    die ('上传文件大小超出了PHP配置文件中的约定值:upload_max_filesize');
                case 2 :
                    die ('上传文件大小超出了表单中的约定值:MAX_FILE_SIZE');
                case 3 :
                    die ('文件只被部分上载');
                case 4 :
                    die ('没有上传任何文件');
                default :
                    die ('未知错误');
            }
        }
    }
    
    
    for ($i = 0; $i < count($_FILES["myfile"]["name"]); $i++) {
        /* 判断上传的文件是否为充许的文件类型 */
        //文件名转数组,第一个元素文件名,第二个元素扩展名
        $fileNameArray = explode(".", $_FILES["myfile"]["name"][$i]);
        //输出文件名数组最后一个元素
        $hz = array_pop($fileNameArray);
        /* 通过判断文件的后缀方式,来决定文件是否是充许上传的文件类型 */
        if (!in_array($hz, $allowtype)) {
            die ("这个后缀是<b>" . $hz . "</b>, 不是充许的文件类型!");
        }
    }
    
    for ($i = 0; $i < count($_FILES["myfile"]["size"]); $i++) {
        /* 判断上传的文件是否为充许尺寸范围内 */
        if ($_FILES["myfile"]["size"][$i] > $size) {
            die ($_FILES["myfile"]["name"][$i]."文件超过了充许的<b>{$size}<b>字节大小!");
        }
    }
    
    for ($i = 0; $i < count($_FILES["myfile"]["name"]); $i++) {
        /* 为了系统安全,也为了同名文件会被覆盖,上传后将文件名使用系统定义 */
        $filename = date("YmdHis") . rand(100, 999) . "." . $hz;
    
        /* 判断是否为上传文件 */
        if (is_uploaded_file($_FILES["myfile"]['tmp_name'][$i])) {
            // 移动文件:从临时空间转移到目标位置
            if (!move_uploaded_file($_FILES["myfile"]['tmp_name'][$i], $path . '/' . $filename)) {
                die ('问题: 不能将文件移动到指定目录。');
            }
        } else {
            die ("问题: 上传文件" . $_FILES["myfile"]['name'][$i] . "不是一个合法文件!");
        }
        /* 如果文件上传成功则输出 */
        echo "文件{$filename}上传成功,保存在目录{$path}中,大小为".$_FILES["myfile"]['size'][$i]."字节
    ";
    }
    

      

    文件下载

    • 使用<a>标签下载,浏览器将判断MIME类型,如果能够识别,则直接在浏览器中打开;对于无法识别的文件类型,则提示下载。
    • 手动设置通知浏览器,需要使用到header()函数,用于设置响应头信息。
    • 常见的HTTP响应头信息如下表所示:
    响应头 说明
    Content-Type 设置脚本的MIME类型和编码格式。例如:header("Content-Type:image/jpg")或者header("
    Content-Type:text/html;charset=utf-8")
    Content-Length 响应文件的大小。例如:header("Content-Length:".filesize($file));
    Content-Disposition 下载文件描述。例如:header("Content-Disposition:attachment;filename='".$filename."'");
    Location 重定向。例如header("Location:../index.php"),跳转到index.php脚本。
    • 注意:header()函数之前不允许输出任何字符。
    • 示例代码:
    $path="uploads";
    $file="20180607091158929.jpg";
    header("Content-Type:image/jpg");//设置响应文件类型
    header("Content-Length:".filesize($path.DIRECTORY_SEPARATOR.$file));//设置响应文件的大小
    header("Content-Disposition:attachment;filename=".$file);
    //ob_clean();//清空缓冲区内容
    //flush();//向浏览器输出在这一行代码之前的内容
    readfile($path.DIRECTORY_SEPARATOR.$file);
    

      

    • 使用Location参数实现重定向示例代码:
    $uname=strtolower( trim($_POST["uname"]));//获取用户名
    $upwd=strtolower(trim($_POST["upwd"]));//获取密码
    
    if($uname=="admin"&&$upwd=="123"){//登陆成功
        header("Location:admin.html");
    }else{//登陆失败
        header("Location:login.html");
    }
    

      

      

    自定义文件上传类

    • 文件上传类示例代码
    <?php
    
    /**
     *支持单文件和多文件上传的类
     * Class FileUpload 文件上传类
     */
    class FileUpload
    {
        //上传参数设置相关属性
        private $path = "./uploads";                    //上传文件保存的路径
        private $allowtype = array('jpg', 'jpeg', 'gif', 'png');    //设置限制上传文件的类型
        private $maxsize = 1000000;                    //限制文件上传大小为1M(字节)
        private $israndname = true;                    //设置是否随机重命名文件, false不随机
    
        //上传文件的属性
        private $originName;                            //源文件名
        private $tmpFileName;                            //临时文件名
        private $fileType;                                //文件类型(文件后缀)
        private $fileSize;                                //文件大小
        private $newFileName;                            //新文件名
        private $errorNum = 0;                            //错误号
        private $errorMess = "";                        //错误报告消息
    
        /**
         * 用于设置成员属性($path, $allowtype,$maxsize, $israndname)
         * 可以通过连贯操作一次设置多个属性值
         * @param    string $key 成员属性名(不区分大小写)
         * @param    mixed $val 为成员属性设置的值
         * @return    object            返回自己对象$this,可以用于连贯操作
         */
        function set($key, $val)
        {
            $key = strtolower($key);
            /**
             * 相关函数说明:
             * bool array_key_exists ( mixed $key , array $array )
             * 数组里有键 key 时,array_key_exists() 返回 TRUE。 key 可以是任何能作为数组索引的值。
             *
             * array get_class_vars ( string $class_name )
             * 返回由类的默认公有属性组成的关联数组。
             *
             * string get_class ([ object $object = NULL ] )
             * 返回对象实例 object 所属类的名字。
             */
            if (array_key_exists($key, get_class_vars(get_class($this)))) {
                $this->setOption($key, $val);
            }
            return $this;
        }
    
        /**
         * 调用该方法上传文件
         * @param    string $fileFile 上传文件的表单名称
         * @return    bool                如果上传成功返回数true
         */
    
        function upload($fileField)
        {
            $return = true;
            /* 检查指定上传文件的存储目录是否合法 */
            if (!$this->checkFilePath()) {
                $this->errorMess = $this->getError();
                return false;
            }
            /* 将文件上传的信息取出赋给变量 */
            $name = $_FILES[$fileField]['name'];
            $tmp_name = $_FILES[$fileField]['tmp_name'];
            $size = $_FILES[$fileField]['size'];
            $error = $_FILES[$fileField]['error'];
    
            /* 如果是多个文件上传则$file["name"]会是一个数组 */
            if (is_Array($name)) {
                $errors = array();
                /*多个文件上传则循环处理 , 这个循环只有检查上传文件的作用,并没有真正上传 */
                for ($i = 0; $i < count($name); $i++) {
                    /*设置文件信息 */
                    if ($this->setFiles($name[$i], $tmp_name[$i], $size[$i], $error[$i])) {
                        if (!$this->checkFileSize() || !$this->checkFileType()) {
                            $errors[] = $this->getError();
                            $return = false;
                        }
                    } else {
                        $errors[] = $this->getError();
                        $return = false;
                    }
                    /* 如果有问题,则重新初使化属性 */
                    if (!$return){
                        $this->setFiles();//使用默认参数值初始化文件属性
                    }
                }
    
                if ($return) {
                    /* 存放所有上传后文件名的变量数组 */
                    $fileNames = array();
                    /* 如果上传的多个文件都是合法的,则通过销魂循环向服务器上传文件 */
                    for ($i = 0; $i < count($name); $i++) {
                        if ($this->setFiles($name[$i], $tmp_name[$i], $size[$i], $error[$i])) {
                            $this->setNewFileName();
                            if (!$this->copyFile()) {
                                $errors[] = $this->getError();
                                $return = false;
                            }
                            $fileNames[] = $this->newFileName;
                        }
                    }
                    $this->newFileName = $fileNames;//文件名数组
                }
                $this->errorMess = $errors;
                return $return;
                /*上传单个文件处理方法*/
            } else {
                /* 设置文件信息 */
                if ($this->setFiles($name, $tmp_name, $size, $error)) {
                    /* 上传之前先检查一下大小和类型 */
                    if ($this->checkFileSize() && $this->checkFileType()) {
                        /* 为上传文件设置新文件名 */
                        $this->setNewFileName();
                        /* 上传文件   返回0为成功, 小于0都为错误 */
                        if ($this->copyFile()) {
                            return true;
                        } else {
                            $return = false;
                        }
                    } else {
                        $return = false;
                    }
                } else {
                    $return = false;
                }
                //如果$return为false, 则出错,将错误信息保存在属性errorMess中
                if (!$return) {
                    $this->errorMess = $this->getError();
                }
    
                return $return;
            }
        }
    
        /**
         * 获取上传后的文件名称
         * @param    void     没有参数
         * @return    string    上传后,新文件的名称, 如果是多文件上传返回数组
         */
        public function getFileName()
        {
            return $this->newFileName;
        }
    
        /**
         * 上传失败后,调用该方法则返回,上传出错信息
         * @param    void     没有参数
         * @return    string     返回上传文件出错的信息报告,如果是多文件上传返回数组
         */
        public function getErrorMsg()
        {
            return $this->errorMess;
        }
    
        /* 设置上传出错信息 */
        private function getError()
        {
            $str = "上传文件<span color='red'>{$this->originName}</span>时出错 : ";
            switch ($this->errorNum) {
                case 4:
                    $str .= "没有文件被上传";
                    break;
                case 3:
                    $str .= "文件只有部分被上传";
                    break;
                case 2:
                    $str .= "上传文件的大小超过了HTML表单中MAX_FILE_SIZE选项指定的值";
                    break;
                case 1:
                    $str .= "上传的文件超过了php.ini中upload_max_filesize选项限制的值";
                    break;
                case -1:
                    $str .= "未允许类型";
                    break;
                case -2:
                    $str .= "文件过大,上传的文件不能超过{$this->maxsize}个字节";
                    break;
                case -3:
                    $str .= "上传失败";
                    break;
                case -4:
                    $str .= "建立存放上传文件目录失败,请重新指定上传目录";
                    break;
                case -5:
                    $str .= "必须指定上传文件的路径";
                    break;
                default:
                    $str .= "未知错误";
            }
            return $str . '<br>';
        }
    
        /* 设置和$_FILES有关的内容 */
        private function setFiles($name = "", $tmp_name = "", $size = 0, $error = 0)
        {
            $this->setOption('errorNum', $error);
            if ($error) {
                return false;
            }
            $this->setOption('originName', $name);
            $this->setOption('tmpFileName', $tmp_name);
            //获取文件扩展名
            $aryStr = explode(".", $name);
            $this->setOption('fileType', strtolower($aryStr[count($aryStr) - 1]));//获取数组最后一个元素值
    
            $this->setOption('fileSize', $size);
            return true;
        }
    
        /* 为单个成员属性设置值 */
        private function setOption($key, $val)
        {
            $this->$key = $val;
        }
    
        /* 设置上传后的文件名称 */
        private function setNewFileName()
        {
            if ($this->israndname) {//生成新随机文件名
                $this->setOption('newFileName', $this->proRandName());
            } else {//保存原始文件名
                $this->setOption('newFileName', $this->originName);
            }
        }
    
        /* 检查上传的文件是否是合法的类型 */
        private function checkFileType()
        {
            if (in_array(strtolower($this->fileType), $this->allowtype)) {
                return true;//文件类型检查符合要求
            } else {
                $this->setOption('errorNum', -1);//-1:未允许类型
                return false;
            }
        }
    
        /* 检查上传的文件是否是允许的大小 */
        private function checkFileSize()
        {
            if ($this->fileSize > $this->maxsize) {
                $this->setOption('errorNum', -2);//-2:文件超过指定大小
                return false;
            } else {
                return true;
            }
        }
    
        /* 检查是否有存放上传文件的目录 */
        private function checkFilePath()
        {
            if (empty($this->path)) {
                $this->setOption('errorNum', -5);//-5:未指定上传文件路径
                return false;
            }
            if (!file_exists($this->path) || !is_writable($this->path)) {
                /*
                 * Linux 系统中采用三位十进制数表示权限,如0755, 0644.
                 * ABCD
                 * A- 0, 表示十进制
                 * B-用户
                 * C-组用户
                 * D-其他用户
                 * ---  -> 0   (no excute , no write ,no read)
                 * --x  -> 1   excute, (no write, no read)
                 * -w-  -> 2   write
                 * -wx  -> 3   write, excute
                 * r--  -> 4   read
                 * r-x  -> 5   read, excute
                 * rw-  -> 6   read, write ,
                 * rwx  -> 7   read, write , excute
                 */
                if (!@mkdir($this->path, 0764)) {
                    $this->setOption('errorNum', -4);//-4:建立存放上传文件目录失败,请重新指定上传目录
                    return false;
                }
            }
            return true;
        }
    
        /* 设置随机文件名 */
        private function proRandName()
        {
            $fileName = date('YmdHis') . "_" . rand(100, 999);
            return $fileName . '.' . $this->fileType;
        }
    
        /* 复制上传文件到指定的位置 */
        private function copyFile()
        {
            if (!$this->errorNum) {
                $path = rtrim($this->path, '/') . DIRECTORY_SEPARATOR;
                $path .= $this->newFileName;
                echo '==============' . $path . "======================<br>";
                //解决上传文件乱码问题iconv("UTF-8","gb2312",$path)
                //move_uploaded_file($this->tmpFileName,iconv("UTF-8","gb2312",$path))
                if (@move_uploaded_file($this->tmpFileName, iconv("UTF-8","gb2312",$path))) {
                    return true;
                } else {
                    $this->setOption('errorNum', -3);//-3:上传失败
                    return false;
                }
            } else {
                return false;
            }
        }
    }
    

      

    • 表单信息处理脚本
    <?php
    require "FileUpLoad.class.php";
    
    $fileUpLoad = new FileUpload();//实例化文件上传类
    
    //初始化上传设置
    $fileUpLoad->set('path', './images')
        ->set('maxsize', 1000000)
        ->set('allowtype', array('jpg', 'jpeg', 'gif', 'png'))
        ->set('israndname',false);
    
    if($fileUpLoad->upload('myfile')){
        print_r($fileUpLoad->getFileName());
    }else{
        print_r($fileUpLoad->getErrorMsg());
    }
    

      

    • 单文件上传客户端
    <!--客户端的设置-->
    <form action="action.php" enctype="multipart/form-data" method="post">
        <input type="hidden" name="MAX_FILE_SIZE" value="1000000">
        <p>请选择要上传的文件:<input type="file" name="myfile"></p>
        <p>文件的描述信息:<textarea name="desc" cols="40" rows="4" placeholder="请输入照片关键信息"></textarea></p>
        <p><input type="submit" name="sub" value="上传"></p>
    </form>
    

      

    • 多文件上传客户端
    <!--客户端的设置-->
    <form action="action.php" enctype="multipart/form-data" method="post">
        <!--设定隐藏域-->
        <input type="hidden" name="MAX_FILE_SIZE" value="1000000">
        <p>请选择要上传的文件:<input type="file" name="myfile[]"></p>
        <p>请选择要上传的文件:<input type="file" name="myfile[]"></p>
        <p>请选择要上传的文件:<input type="file" name="myfile[]"></p>
        <p><input type="submit" name="sub" value="上传"></p>
    </form>
    

      



    本博客文章未经许可,禁止转载和商业用途!

    如有疑问,请联系: 2083967667@qq.com


  • 相关阅读:
    django页面分类和继承
    django前端从数据库获取请求参数
    pycharm配置django工程
    django 应用各个py文件代码
    CF. 1428G2. Lucky Numbers(背包DP 二进制优化 贪心)
    HDU. 6566. The Hanged Man(树形背包DP DFS序 重链剖分)
    小米邀请赛 决赛. B. Rikka with Maximum Segment Sum(分治 决策单调性)
    区间树 学习笔记
    CF GYM. 102861M. Machine Gun(主席树)
    2016-2017 ACM-ICPC East Central North America Regional Contest (ECNA 2016) (B, D, G, H)
  • 原文地址:https://www.cnblogs.com/rask/p/9016386.html
Copyright © 2020-2023  润新知