学习要点
- 文件系统概述
- 目录基本操作
- 文件基本操作
- 文件上传下载
- 文件上传类的设计
文件系统概述
概述
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
= 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():返回路径关联数组
示例代码
遍历目录
- 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 "";
echo "" . $fileName . "下的文件信息
";
echo "文件名 文件类型 文件大小 文件修改日期 ";
$count = 0;//统计有多少个文件
while ($file = readdir($dirHandler)) {//2.遍历每个文件
$count++;
//构建目录下文件或者目录的路径
$filePath = $fileName . DIRECTORY_SEPARATOR . $file;
//隔行变色
if ($count % 2 == 1) {
echo "";
} else {
echo " ";
}
echo "" . $file . " ";//文件名
//文件类型
if(filetype($filePath)=="dir"){
echo "文件夹 ";
}else if(filetype($filePath)=="file"){
echo "文件 ";
}else{
echo "未知文件类型 ";
}
echo "" . getFileSize(filesize($filePath)) . " ";//文件大小
echo "" . date("Y-m-d H:i:s", filemtime($filePath)) . " ";//文件修改日期
echo " ";
}
echo "" . $fileName . "目录下文件数量:" . $count . " ";
echo "
";
closedir($dirHandler);//3.关闭目录句柄
统计目录大小
- 设计递归函数统计目录大小
- filesize()函数
- 示例代码
创建和删除目录
- 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 "创建目标路径成功!\n";
}
//目录拷贝工作
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: \n
WIN: \r\n
Mac: \r
- 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}行数据!\r\n",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协议看服务器是否支持写
- 示例代码:读取网页中
标签中的信息
//打开文件
$fileHandler=fopen("https://www.cnblogs.com/rask/p/9016386.html","r") or die("打开文件失败");
while (!feof($fileHandler)){
$line=fgets($fileHandler,4096);
if(preg_match("/(.*)<\/h1>/",$line,$out)){//()子模式
echo $out[1];
print_r($out);
break;
}
}
//关闭文件
fclose($fileHandler);
上机练习2:二进制文件的读取
需求描述:读取硬盘上的图片,显示在网页上
上机练习3:http网页的读取
需求描述:
1.读取http页面
2.解析
标签内容
移动文件指针
- 文件指针度量单位:字节
- 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 ) . "
"; // 输出刚打开文件的指针默认位置,指针在文件的开头位置为0
echo fread ( $fp, 10 ) . "
"; // 读取文件中的前10个字符输出,指针位置发生了变化
echo ftell ( $fp ) . "
"; // 读取文件的前10个字符之后,指针移动的位置在第10个字节处
fseek ( $fp, 100, SEEK_CUR ); // 将文件指针的位置,由当前位置向后移动100个字节数
echo ftell ( $fp ) . "
"; // 文件位置在110个字节处
echo fread ( $fp, 10 ) . "
"; // 读取110到120字节数位置的字符串,读取后指针的位置为120
//echo ftell ( $fp );
fseek ( $fp, - 10, SEEK_END ); // 又将指针移动到倒数10个字节位置处
echo ftell ( $fp ). "
";
//echo fread ( $fp, 10 ) . "
"; // 输出文件中最后10个字符
rewind ( $fp ); // 又移动文件指针到文件的开头
echo ftell ( $fp ) . "
"; // 指针在文件的开头位置,输出0
fclose ( $fp ); //关闭文件资源
文件锁定机制
bool flock ( resource $handle , int $operation [, int &$wouldblock ] )
说明:flock() 允许执行一个简单的可以在任何平台中使用的读取/写入模型(包括大部分的 Unix 派生版和甚至是 Windows)。
在 PHP 5.3.2版本之前,锁也会被 fclose() 释放(在脚本结束后会自动调用)。
PHP 支持以咨询方式(也就是说所有访问程序必须使用同一方式锁定, 否则它不会工作)锁定全部文件的一种轻便方法。 默认情况下,这个函数会阻塞到获取锁;这可以通过下面文档中 LOCK_NB 选项来控制(在非 Windows 平台上)。
留言板关键示例代码
”结尾
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 . "
"; // 输出留言主题信息
}
}
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。
- 示例代码
文件上传
- 客户端设置
1、设置表单数据编码格式
enctype="multipart/form-data"
2、设置表单的数据传输方法
method="post"
3、设置隐藏域,提示用户上传文件大小限制
-
服务器端处理上传文件
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 ( "这个后缀是" . $hz . ", 不是充许的文件类型!" );
}
/*
* 也可以通过获取上传文件的MIME类型中的主类型和子类型,来限制文件上传的类型
* list($maintype,$subtype)=explode("/",$_FILES['myfile']['type']);
* if ($maintype=="text") { //通过主类型限制不能上传文本文件,例如.txt .html .php等文件
* die('问题: 不能上传文本文件。'); //如果用户上传文本文件则退出程序
* }
*/
/* 判断上传的文件是否为充许尺寸范围内 */
if ($_FILES ['myfile'] ["size"] > $size) {
die ( "超过了充许的{$size}字节大小!" );
}
/* 为了系统安全,也为了同名文件会被覆盖,上传后将文件名使用系统定义 */
$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']}字节";
- 多文件上传示例:
客户端代码:
服务器端代码:
$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 ("这个后缀是" . $hz . ", 不是充许的文件类型!");
}
}
for ($i = 0; $i < count($_FILES["myfile"]["size"]); $i++) {
/* 判断上传的文件是否为充许尺寸范围内 */
if ($_FILES["myfile"]["size"][$i] > $size) {
die ($_FILES["myfile"]["name"][$i]."文件超过了充许的{$size}字节大小!");
}
}
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]."字节\n";
}
文件下载
- 使用标签下载,浏览器将判断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");
}
自定义文件上传类
- 文件上传类示例代码
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 = "上传文件{$this->originName}时出错 : ";
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 . '
';
}
/* 设置和$_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 . "======================
";
//解决上传文件乱码问题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;
}
}
}
- 表单信息处理脚本
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());
}
- 单文件上传客户端
- 多文件上传客户端