目录
1.2 文件操作
1.将字符串写到文件中
<?php
header("Content-type:text/html;charset=utf-8");
// 1、将字符串写到文本中
$str="1\r\n2\r\n3\r\n4\r\n5";
file_put_contents('./test.txt',$str);
?>
小结:
1、所有的写操作都是清空重写即覆盖
2、在文本中换行是\r\n windows
\r:光标移动到当前行的最前面
\n:将光标向下移动一行
Enter键=\r\n 计算机做了两步 移动到当前行的最前面 再向下移动一行
3、\r\n是特殊字符 必须放在“ ”内部 在单引号内部就是写入字符串
2、读取文件和读取并且输出文件
echo file_get_contents('./test.txt'); //将整个文件读入一个字符串中再输出
readfile('./test.txt'); //读取输出文件内容
3、打开文件并操作
fopen(地址,模式) 打开文件夹
模式:
r:读 read
w:写 write
a:追加 append
例题:
// 3、打开文件并进行操作
$fp=fopen('./test.txt', 'w'); //打开文件返回文件指针(文件地址 )
//var_dump($fp); //resource(6) of type (stream)
for ($i=1; $i <=10 ; $i++)
{
fputs($fp,"关关雎鸠\r\n"); //循环十次写入关关雎鸠 每写一次就换行
}
fclose($fp); //关闭文件
4、打开文件读取
$fp=fopen('./test.txt','r'); //打开文件读取 默认只读一行
while ($line=fgets($fp)) {
echo $line.'<br>'; //循环读取
}
5、打开文件追加
$fp=fopen('./test.txt','a'); //打开文件追加
fputs($fp,'在河之洲'); //在文件的末尾增加
小结:
1、打开文件 返回文件指针(文件指针即文件地址)返回资源类型
2、打开文件写、追加的操作 。如果文件不存在,那就创建一个新的文件
3、打开文件读操作, 文件不存在就报错
4、fputs写一行、fgets读一行、fclose关闭文件 如果你不关闭 计算机也会帮你关闭?(不太理解)
5、追加是在文件末尾追加
6、是否是文件
echo is_file('./test.txt')?'是':'不是'; // 三元运算符判断是否是文件
7、判断文件或文件夹是否存在
echo file_exists('./test.txt')?'存在':'不存在';
8、删除文件【unlink】
// 给出一个文件路径
$path='./test.txt';
//判断文件是否存在
if (file_exists($path)) {
//如果是文件夹 用rmdir删除
if (is_dir($path)) {
rmdir($path);
//如果是文件,用unlink删除文件
}elseif (is_file($path)) {
unlink($path);
}
# 否则输出文件不存在
}else{
echo '文件不存在';
}
我这里是存在的 但是不知道为啥被拒绝了权限 有知道的师傅可以告诉我一下
9、ASCII美国信息交换标准代码
分为两种 一种可见 一种不可见 键盘上每一个键都是ASCII码 控制字符和可见字符
10、二进制读取【fread(文件指针,文件大小)】
文件的存储有两种形式:字符流和二进制流
二进制的读取按文件大小来读的
$a='C:\Users\lyr\Desktop\13jpg.jpg';
$c=fopen($a,'r');
header('content-type:image/jpeg'); //告知浏览器下面的代码通过jpg方式解析
echo fread($c,filesize($a)); //二进制的读取
//多学一招
header('content-type:image/jpeg');
echo file_get_contents('C:\Users\lyr\Desktop\13jpg.jpg');
//file_get_contents既能读字符串又能读二进制文件
运行结果如下
小结:
1、文本流有明确的结束符,二进制流没有明确的结束符号,通过文件大小判断文件是否读取完毕。
2、file_get_contents() 既可以进行字符流的读取,也可以进行二进制的读取。
1.3表单提交数据的两种方式
1.3.1 两种方式
1、get
2、post
<form action=" " method="post" accept-charset="utf-8">
<form action=" " method="get" accept-charset="utf-8">
tips:如果form action不写就是提交到本页面上
1.3.2 区别
1、从外观上看
get提交在地址上可以看到参数 post提交在地址栏看不到到参数
2、安全性
get不安全 post安全
3、提交原理
get提交是将参数一个个的提交
post提交是将所有参数作为一个整体提交
4、提交数据的大小
get提交一般不超过255个字符
post提交的大小取决于服务器
5、灵活性
get很灵活,只要有页面得到跳转就可以传递参数(不要传递敏感数据)
post不灵活,post提交需要有表单的参与
1、html跳转
<a href="./P82 File domain enctype.php?name=tom&age=20">跳转</a>
2、js跳转
<script type="text/javascript">
location.href='P82 File domain enctype.php?name=tom&age=20';
location.assign('P82 File domain enctype.php?name=tom&age=20');
location.replace('P82 File domain enctype.php?name=tom&age=20');
</script>
3、php跳转
<?php
header('location:P82 File domain enctype.php?name=tom&age=20')
?>
GET | POST | |
---|---|---|
外观上 | get提交在地址上可以看到参数 | post提交在地址栏看不到到参数 |
提交数据大小 | get提交一般不超过255个字符(IE)最大值不同浏览器不一样 | 提交大量数据,可以通过php.ini配置文件来设置post提交的参数 |
安全性 | get不安全 | post安全 |
提交原理 | 提交的数据之间是独立的 | 将提交的数据变成XML格式提交 |
灵活性 | 很灵活,只要有页面的跳转就能传递数据 | 不灵活 |
1.4 服务器接收数据的三种方式
通过名字获取名字对应的值
$_POST:数组类型 保存POST提交的数据
$_GET:数组类型 保存GET提交的数据
$_REQUEST:既能获取POST又能获取GET的值
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<title>服务器接收数据</title>
</head>
<body>
#表单提交数据
<form action="" method="get" accept-charset="utf-8">
语文<input type="text" name="ch" value="" placeholder=""><br>
英语<input type="text" name="ma" value="" placeholder=""><br>
<input type="submit" name="button" value="提交">
</form>
#超链接提交数据
<a href="P83 Server receiving data.php?ch=88&ma=55">跳转</a><br>
#js提交数据
<script type="text/javascript">
function fun(){
location.href='./P83 Server receiving data.php?ch=88&ma=55'
}
</script>
<input type="button" value="点击" onclick="location.href='./P83 Server receiving data.php?ch=99&ma=55'"><br>
<?php
if (!empty($_GET)) {
echo '这是get提交的数据'.'<br>';
echo '语文:'.$_GET['ch'].'<br>';
echo '数学:'.$_GET['ma'].'<br>';
echo '<hr>';
echo '语文:'.$_REQUEST['ch'].'<br>';
echo '数学:'.$_REQUEST['ma'].'<br>';
}
?>
</body>
</html>
思考题:
在一个请求中既有get又有post,get和post传递的名字一样的时候,通过$_REQUEST获取的数据是什么?
答案:取决于配置文件php.ini 先获取get的值 再获取post的值
例题:
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<title>REQUEST</title>
</head>
<body>
<form action="P80 Request.php?username=berry" method="post" accept-charset="utf-8">
<input type="text" name="username" value="" placeholder="">
<input type="submit" name="button" value="提交">
</form>
// 分析:先获取get的username 再获取post的username 后面的值将前面的值覆盖
<?php
if (!empty($_POST)) {
echo 'name:'.$_REQUEST['username'].'<br>';
}
?>
</body>
</html>
小结:
1、在开发的时候,如果明确是post提交就用$_POST获取数据, get同理
2、request获取效率低,尽可能不要使用,除非提交的类型不确定的情况才能使用
1.5 参数传递
1.5.1 复选框的传递
复选框的命名要注意带 [ ](英文输入法)!!!
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>参数传递</title>
</head>
<body>
<form action=" " method="post" accept-charset="utf-8">
爱好: <input type="checkbox" name="hobby[]" value="爬山">爬山
<input type="checkbox" name="hobby[]" value="抽烟">抽烟
<input type="checkbox" name="hobby[]" value="喝酒">喝酒
<input type="checkbox" name="hobby[]" value="烫头">烫头
<input type="submit" name="button" value="提交">
</form>
<hr>
<?php
if (isset($_POST['button'])) {
//var_dump($_POST);
echo '<br>';
print_r($_POST['hobby']) ;
}
?>
运行结果:
小结:
1、表单提交到本页面需要判断一下是否有POST提交
2、数组的提交表单元素名字必须带有[ ]
1.5.2例题
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>参数传递</title>
</head>
<body>
<form action=" " method="post" accept-charset="utf-8">
姓名: <input type="text" name="username" value="" placeholder="请输入你的用户名"> <br/>
密码: <input type="password" name="pwd" value="" placeholder="请输入你的密码"> <br/>
性别: <input type="radio" name="sex" value="男" placeholder="" checked="男"> 男
<input type="radio" name="sex" value="女" placeholder=""> 女 <br>
爱好: <input type="checkbox" name="hobby[]" value="爬山">爬山
<input type="checkbox" name="hobby[]" value="抽烟">抽烟
<input type="checkbox" name="hobby[]" value="喝酒">喝酒
<input type="checkbox" name="hobby[]" value="烫头">烫头<br>
籍贯:
<select name="jiguan" >
<option value="上海">上海</option>
<option value="北京">北京</option>
</select><br>
留言: <textarea name="words" rows="5" cols="30"></textarea>
<input type="submit" name="button" value="提交">
</form>
<hr>
<?php
if (isset($_POST['button'])) {
var_dump($_POST);
echo '<hr>';
echo '姓名:'.$_POST['username'].'<br>';
echo '密码:'.$_POST['pwd'].'<br>';
echo '性别:'.$_POST['sex'].'<br>';
echo '爱好:'.(isset($_POST['hobby'])?implode(',', $_POST['hobby']):'没有爱好'.'<br>');
echo '籍贯:'.$_POST['jiguan'].'<br>';
echo '留言:'.$_POST['words'];
echo '<hr>';
print_r(isset($_POST['hobby'])?$_POST['hobby']:'没有爱好'.'<br>');
}
?>
</body>
</html>
运行结果:
1.6 文件上传
开发中需要上传图片、音乐、视频等等,这种上传是二进制数据
1.6.1 客户端上传文件
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<title>文件上传</title>
</head>
<body>
<form action="" method="post" enctype="application/x-www-form-urlencoded">
//将表单中的数据转成xml一起提交 这个只能传输字符串 带格式的xml文档
<input type="file" name="" >
</form>
<form action="" method="post" enctype="multipart/form-data">
//既能传字符串也能传二进制
<input type="file" name="" >
</form>
</form>
<form action="" method="post" enctype="text/plain">
//类似记事本样的字符串 不带格式那种 主要用来做电子邮件
<input type="file" name="" >
</form>
</body>
</html>
补充:xml和html的区别
<username>tom</username>
<sex>a</sex>
xml和html的唯一区别在于 xml可以自定义而html是定义好的
xml叫可扩展标签 好像标签也是成对出现的
表单的enctype属性
默认情况下,表单传递的是字符流,通过设置表单的enctype属性传递复合数据
enctype属性的值有:
1.application/x-www-form-urlencoded:【默认的】表示传递的是带格式的文本数据
2.multipart/form-data: 复合的表单数据 【字符串,文件】文件上传必须设置此值
3.text/plain: 用于向服务器传递无格式的文本数据,主要用于用户电子邮件,速度快效率高
单词
multipart:复合
form-data:表单数组
1.6.2 服务器接收文件
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<title>$_FIlES</title>
</head>
<body>
<?php
if(!empty($_POST)){
echo '<pre>';
print_r($_FILES);
}
?>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="image" ><br>
<input type="submit" name="button" value="提交">
</form>
</body>
</html>
超全局变量$_FILES是一个二维数组,用来保存客户端上传到服务器的文件信息。二维数组的行是文件域的名称,列有5个。
1、$_FILES[]['name'] #上传的文件名
2、$_FILES[]['type'] #上传的文件类型,这个类型是MIME类型(image/jpeg image/gif image/png)
3、$_FILES[]['size'] #文件的大小,以字节为单位
4、$_FILES[]['tmp_name'] #文件上传时候的临时文件
5、$_FILES[]['error'] #错误编码(值有0、1、2、3、4、6、7)0表示正确
$_FILES[]['error']详解
值 错误描述
0 正确
1 文件大小超过了php.ini中的最大值
2 文件大小超过了表单允许的最大值
3 只有部分上传
4 没有文件上传
6 找不到临时文件
7 文件写入失败
**注意:MAX_FILE_SIZE必须在文件域的上面**!!! 我这里写错了
**只要掌握的错误号:0和4**
1.6.3 将上传文件移动到指定位置
move_uploaded_file
也就是说也有可能是不用http post也可以上传文件的 具体方法我不太了解 以后知道了再补充上
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<title>$_FIlES</title>
</head>
<body>
<?php
if(!empty($_POST)){
if ($_FILES['image']['error']==0) {
echo $_FILES['image']['error'].'<br>';
move_uploaded_file($_FILES['image']['tmp_name'], './'.$_FILES['image']['name']);
}else{
echo '上传有误';
}
}
?>
<form action="" method="post" enctype="multipart/form-data">
<!-- <input type="hidden" name="MAX_FILE_SIZE" value="2"> -->
<input type="file" name="image" ><hr>
<input type="submit" name="button" value="提交">
</form>
</body>
</html>
小结:上传的同名文件会被覆盖 所以需要对文件进行重命名
1.6.4 与文件上传有关的配置
post_max_size = 8M: 表单允许的最大值
upload_max_filesize = 2M: 允许上传的文件大小
upload_tmp_dir = E:\wamp\wamp\www\f.com\tmp : 指定临时文件地址,如果不知道操作系统指定
file_uploads = On : 是否允许文件上传
max_file_uploads = 20 : 允许同时上传20个文件
1.7 优化文件上传
1.7.1 更改文件名
方法一:通过时间戳做文件名
<?php
$path='face.jpg';
$b= time();
echo '<hr>';
$a=strrchr($path, '.'); //从右边开始第一个.开始截取到最后
echo $b.rand(111,999).$a;
?>
//输出结果:1650032734405.jpg
方法二:通过uniqid()实现
$path='face.stu.jpg';
echo uniqid().strrchr($path, '.').'<br>'; //生成唯一的id
echo uniqid('goods_').strrchr($path, '.').'<br>'; //带有前缀
echo uniqid('goods_',true).strrchr($path, '.').'<br>'; //唯一ID+随机数
1.7.2验证文件格式
方法一:判断文件的扩展名(不能识别文件伪装)
操作思路:将允许的文件后缀和上传的文件后缀做对比
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>验证格式</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<!-- <input type="hidden" name="MAX_FILE_SIZE" value="2"> -->
<input type="file" name="image" ><hr>
<input type="submit" name="button" value="提交">
</form>
<?php
if (!empty($_POST)) {
// echo '<pre>';
// print_r($_FILES);
$a=strrchr($_FILES['image']['name'], '.');
echo $a;
$allow=array('.jpg','.png','.gif'); //允许的扩展名
if (in_array($a,$allow)) {
echo '上传成功';
}else{
echo '上传失败';
}
}
?>
</body>
</html>
上传图片木马成功 白名单的话还可以考虑0x00截断
方法二:通过$_FILES比较mime类型(不能防止文件伪装)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>验证格式</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<!-- <input type="hidden" name="MAX_FILE_SIZE" value="2"> -->
<input type="file" name="image" ><hr>
<input type="submit" name="button" value="提交">
</form>
<?php
if (!empty($_POST)) {
// echo '<pre>';
// print_r($_FILES);
$a=$_FILES['image']['type'];
echo $a.'<br>';
$mime=array('image/jpeg','image/png','image/gif'); //允许的扩展名
if (in_array($a,$mime)) {
echo '上传成功';
}else{
echo '上传失败';
}
}
?>
</body>
</html>
上传一个伪装成jpg的php文件可以成功上传 你懂我意思吧
方法三:开启php_fileinfo扩展(可以防止文件伪装)
注意:开启fileinfo扩展以后就可以使用finfo*开头的函数了
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>验证格式</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<!-- <input type="hidden" name="MAX_FILE_SIZE" value="2"> -->
<input type="file" name="image" ><hr>
<input type="submit" name="button" value="提交">
</form>
<?php
if (!empty($_POST)) {
// echo '<pre>';
// print_r($_FILES);
// 第一步:创建finfo资源
$info=finfo_open(FILEINFO_MIME_TYPE);
var_dump($info);
echo '<hr>';
//var_dump($info).'<br>';
// 第二步:将info资源和文件做比较
$mime=finfo_file($info,$_FILES['image']['tmp_name']);
echo $mime.'<br>';
// 第三步:比较是否合法
$allow=array('image/jpeg','image/png','image/gif');
echo in_array($mime,$allow)?'allow':'not allow';
$a=$_FILES['image']['type'];
echo $a.'<br>';
$mime=array('image/jpeg','image/png','image/gif'); //允许的扩展名
if (in_array($a,$mime)) {
echo '上传成功';
}else{
echo '上传失败';
}
}
?>
</body>
</html>
上传一个伪装为jpg的php文件无法成功
但是上传一个图片木马可以成功
小结:fileinfo_file()并不安全
1.7.3 优化文件上传例题
步骤:
1、验证是否有误
2、验证格式
3、验证大小
4、验证是否是http上传
5、上传实现
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>文件上传验证</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="img" ><hr>
<input type="submit" name="button" value="提交">
</form>
<?php
// 验证错误
function check($file){
$error=$file['error'];
if ($error!==0) {
switch ($error) {
case '1':
echo'文件大小超过了php.ini中的最大值,最大值是:'.ini_get_all('upload_max_filesize');# code...
return false;
case '2':
echo'文件大小超过了表单允许的最大值';# code...
return false;
case '3':
echo' 只有部分上传';# code...
return false;
case '4':
echo'没有文件上传';# code...
return false;
case '6':
echo'找不到临时文件';# code...
return false;
case '7':
echo'文件写入失败';# code...
return false;
default:
echo '未知错误';
return false;
}
}
// 2、验证格式
$info=finfo_open(FILEINFO_MIME_TYPE);
$mime=finfo_file($info,$file['tmp_name']);
$allow=array('image/jpeg','image/png','image/gif');
$a=array('jpeg','png','gif');
if (!in_array($mime,$allow)) {
echo '只能上传'.implode('/', $a);
return false;
}
// 3、验证大小
$size=999999;
if ($file['size']>$size) {
echo '文件大小超过'.number_format($size/1024,1).'K';
}
//4 、验证是否是HTTP上传
if (!is_uploaded_file($file['tmp_name'])) {
return '文件不是http post 上传的';
}
echo '文件上传成功';
}
//表单提交
if (!empty($_POST)) {
// 验证是否有错误
if ($error=check($_FILES['img'])) {
echo $error;
}else{
//文件上传,上传的文件保存在当天的文件夹中
$foldername=date('Y-m-d');
$folderpath="./uploads/{$foldername}";
if (!is_dir($folderpath))
mkdir($folderpath);
$filename=uniqid(' ',true).strrchr($_FILES['img']['name'], '.');
$filepath="$folderpath/$filename";
if (move_uploaded_file($_FILES['img']['tmp_name'], $filepath))
echo "上传成功,路径是:{$foldername}/{$filename}";
else
echo '上传失败';
}
}
?>
</body>
</html>
小结:
1、将时间戳转换格式
echo date('Y-m-d H:i:s',1231346).'<br>'; #将时间戳转换为年-月-日 小时-分钟-秒
echo date('Y-m-d H:i:s'); #将当前时间转换成年-月-日 小时-分钟-秒
2、设置时区
3、PHP的执行可以不需要Apache的参与 可以在本地运行文件