• 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


  • 相关阅读:
    RHEL iptables
    搭建类似生产环境的RAC
    [大数据入门] Cloudera-Hadoop 理论
    js中的正则表达式【常用】
    html-css-js基本理解和简单总结
    python的socket.recv函数陷阱
    python异步编程--回调模型(selectors模块)
    python并发学习总结
    python描述符学习
    python网络编程基础
  • 原文地址:https://www.cnblogs.com/rask/p/9016386.html
Copyright © 2020-2023  润新知