一、文件上传
文件上传的基础知识:
- 首先,在客户端form表达设置,选择上传的文件
- 然后,在服务器对上传文件进行操作处理
1.1 关于前台页面
必须设置 form 表单项:
<html><head><title>文件上传</title></head><body><from action="./upload.php" method="post" enctype="multipart/form-data">选择文件: <input type="file" name="myfile"><input type="submit" value="上传文件"></from></body>
</html>
注意事项
- 一定是post方式上传文件,不可用get方式。
- form 表单中一定要些enctype="multipart/form-data"。
- input 表单一定要写name,后端的php是基于name来接收上传的文件的。
1.2 后端的php程序
1. 通过PHP脚本来处理的,具体需要通过以下三个方面信息
2. 后端的PHP文件,是基于一个数组来接收传入的文件的,这个数组是一个内置数组【二维数组】:
$_FILES
数组的索引值
注意: html的input标签的name的值是myfile$_FILES["myfile"]["error"]: 记录文件上传过程中,是否发生了错误,如果这里的值大于0,那么就发生了错误:否则上传成功 $_FILES["myfile"]["name"]: 上传的文件名称 $_FILES["myfile"]["tmp_name"]: 文件被上传到服务器后,文件在服务器上的文件名 $_FILES["myfile"]["type"]: 上传文件的文件类型 $_FILES["myfile"]["size"]: 上传文件的大小,默认单位是字节
1.3 php的文件上传处理函数
上传成功的文件会被放置到服务器端临时目录下,文件名是随机生成的临时文件名。
注:该文件在程序执行完后将自动删除掉。在删除前可以像本地文件一样操作。
文件上传处理函数:
is_uploaded_file - 判断文件是否通过 HTTP POST 上传的。 格式:is_uploaded_file (strint $filename) 返回结果:布尔值move_uploaded_file - 将上传的文件移动到新位置 格式:move_uploaded_file (string $filename,strint $destination) 返回结果:布尔值 注意1:第二个参数不能是目录,而应该是目录下的某个文件,例如 ./dir1/abcd.html 注意2:上传的文件名中如果有中文的话,默认会导致移动失败,解决方法是用iconv将文件编码修改为gbk。 注意3:如果目标文件已经存在,将会被覆盖。
案例:
前台页面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><from action="./upload.php" method="post" enctype="multipart/form-data">//必须要写选择文件:<input type="file" name="myfile"><input type="submit" value="上传文件></from>
</body>
</html>
后台程序
<?phpheader("Content-type:text/html;charset=utf-8");// myfile 是前台的html页面中的name属性的值// $_FILES['myfile']['error'] 数组可以判断是否上传成功if ($_FILES['myfile']['error'] > 0){echo "上传发生错误".$_FILES['myfile']['error']."<br>";}else{echo "文件上传成功<br>";echo "文件名称:".$_FILES['myfile']['name']."<br>";echo "文件类型:".$_FILES['myfile']['type']."<br>";echo "文件大小:".$_FILES['myfile']['size']."<br>";echo "文件临时存储位置:".$_FILES['myfile']['tmp_name']."<br>";# $_FILES['myfile']['name'] 保存的文件名,但是文件名如果有中文,会导致失败# 用 iconv 将文件名编码修改为gbk# 最终用 $fileName 保存修改编码后的文件名$fileName = iconv("UTF-8","GBK",$_FILES['myfile']['name']);// 将临时存储的文件移动到当前位置下的abcd目录中// 移动过去后将文件名修改为原始名字$res = move_uploaded_file($_FILES['myfile']['tmp_name'],"./abcd/".$fileName);if($res){// 最后在页面上需要显示文件名,所以需要将编码从gbk修改回utf-8$fileName = iconv("GBK","UTF-8",$fileName);echo "文件成功移动到./abcd/".$fileName;}else{echo "文件移动失败";}}
?>
1.4 扩展内容
PHP 配置文件中与文件上传有关的选项
指令名 | 默认值 | 功能描述 |
file_uploads | ON | 是否开启文件上传 |
upload_max_filesize | 2M | 限制PHP处理上传文件的最大值,此值必须小于post_max_size |
post_max_size | 8M | 限制通过POST方法可以接收信息的最大值,也就是整个POST请求的提交值。此值必须大于 upload_max_filesize |
upload_tmp_dir | NULL | 上传文件存放的临时路径,可以是绝对路径。默认NULL 则使用系统的临时目录。 |
max_file_uploads | 20 | 文件允许同时上传的个数 |
关于 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 引进
常见数据格式(MIME)
文件类型 | MIME 类型 |
图片文件 | image/gif,image/jpg,image/jpeg,image/png,image/x-png |
纯文本和HTML | text/txt,text/plan,text/html |
二进制文件 | application/octet-stream |
音频格式 | audio/basic |
视频格式 | video/mpeg |
案例:
1、设置前端上传界面
<from action="upload.php" method="post" enctype="multipart/form-data"><input type="file" name="myfile"><input type="submit" value="上传"> </from>
2、upload.php 处理上传到临时目录的文件
<?php header("Content-type:text/html;charset=utf-8");if ($_FILES['myfile']['error']>0){echo "上传发生错误".$_FILES['myfile']['error']."<br>";}else{echo "文件名称:".$_FILES['myfile']['name']."<br>";echo "文件类型:".$_FILES['myfile']['type']."<br>";echo "文件大小:".($_FILES['myfile']['size']/1024)."KB<br>";echo "文件临时存储位置:".$_FILES['myfile']['tmp_name']."<br>";} ?>====================================================================================<?phpif ($_SERVER["REQUEST_METHOD"] == "POST") {$file = $_FILES["file"];// 检查文件是否上传成功if ($file["error"] == UPLOAD_ERR_OK) {$uploadPath = "uploads/".$file["name"];//将临时文件移动到目标路径if (move_uploaded_file($file["tmp_name"],$uploadPath)) {echo "文件上传成功!";} else {echo "文件上传失败!";}} else {echo "文件上传出错:".$file["error"]'}} ?>
封装成函数:
思路
function upload(){//1.判读文件是否上传错误//2.判断文件上传的类型是否是你想要的类型//3.起名字//4.判断保存路径是否存在//5.判断是否是http post方式上传//6.移动图片//7.返回移动成功的图片名 }
开始封装函数:新建 function php
<?php /*文件上传函数@param string $name 文件上传域的name值@param strint $dir 文件保存路径@param array $allow 文件允许上传的类型return string $filename 文件名 如果失败 返回false */function upload($name,$dir='./upload/',$allow=array('jpg','gif','jpeg','png')){// 1.判断文件上传错误if($_FILES[$name]['error']>0){switch($_FILES[$name]['error']){case 1:echo '上传的文件超过了 php.ini 中upload_max_filesize 选项限制的值';break;case 2:echo '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值';break;case 3:echo "文件只有部分被上传";break;case 4:echo '没有文件被上传';break;case 6:echo '找不到临时文件夹';break;case 7:echo '文件写入失败';break;}return false;}// 2.判断文件上传的类型是否是你想要的类型// 2.1允许上传的类型// 2.2获取后缀名$suffix = pathinfo($_FILES[$name]['name'],PATHINFO_EXTENSION);// 2.3 判断是否是我们允许上传的类型if (!in_array($suffix,$allow)){//不允许上传的类型echo '大哥你的上传类型不符合';return false;}// 3.起名字$filename = date('Ymd').uniqid().mt_rand(0,9999).'.'.$suffix;// 4.判断保存路径是否存在// 4.1 得到保存路径// 4.2 处理保存路径和否面的斜杠$save_path = rtrim($dir,'/');$save_path .= '/';// 4.3 保存路径中的时间文件夹处理$save_path .= date('Y/m/d/');// 4.4 判断保存的路径是否存在if (!file_exists($save_path)){mkdir($save_path,777,true);}// 4.5 拼接一个完整的保存路径$path = $save_path.$filename// 5.判断是否是httppost方式上传if (!is_uploaded_file($_FILES[$name]['tmp_name'],$path)){echo '移动失败';return false;}// 7.返回移动成功的文件名return $filename; }?>
调用函数开始上传:
<?phpinclude './function.php';echo upload('file','./leiding',array('jpg','png'));
参考版本
<?php//第一步:明确服务器规定上传至服务器的文件类型。这里我们只允许上传以下类型的图片。$allowedExts = array("git","jpeg","jpg","png");// 允许上传的图片后缀//第二步:获取上传的文件名称,通过explorde()函数将其分割成字符串形式的数组。$temp = explode(".",$_FILES['myfile']['name']);echo $_FILE['myfile']['size'];$extension = end($temp); //end函数用于获取数组中最后一个元素的值。//第三步:列出上传文件需要满足的if ((($_FILES['myfile']['type'] == 'image/gif')|| ($_FILES['myfile']['type'] == 'image/jpeg')|| ($_FILES['myfile']['type'] == 'image/jpg')|| ($_FILES['myfile']['type'] == 'image/pjpeg')|| ($_FILES['myfile']['type'] == 'image/x-png')|| ($_FILES['myfile']['type'] == 'image/png'))&& ($_FILES['myfile']['size'] < 204800 ) // 小于 200 kb&& in_array($extension,$alloweExts)) //in_array表示在$allowedExts数组中查找$extension这个字符串{if ($_FILES["myfile"]["error"] > 0){echo "错误::".$_FILES["myfile"]["error"]."<br>";} else {echo "上传文件名:".$_FILES["myfile"]["name"]."<br>";echo "文件类型:".$_FILES['myfile']['type']."<br>";echo "文件大小:".($_FILES['myfile']['size'] / 1024)."<br>";echo "文件临时存储位置:".$_FILES['myfile']['tmp_name']."<br>";// 判断当前目录(即www文件夹中)下的upload目录(自己创建,名字自取)是否存在该文件// 如果没有upload目录,你需要创建它,upload目录权限为777if (file_exists("upload/".$_FILES['myfile']['name'])){echo $_FILES['myfile']['name'].'文件已经存在。';} else {//如果upload目录不存在该文件则将文件上传到upload目录下move_upload_file($_FILES['myfile']['tmp_name'],"upload/".$_FILES['myfile']['name']);echo "文件存储在:"."upload/".$_FILES['myfile']['name'];}}} else {echo "非法的文件格式";}
?>
多文件上传
不同 name 名称多文件上传
当需要上传多个文件,有两种解决方法:
1、使用不同的表单元素
<input type="file" name="file_a"> <input type="file" name="file_b"> <input type="file" name="file_c">
2、使用数组格式的表单元素
<input type="file" name="file[]"> <input type="file" name="file[]"> <input type="file" name="file[]">
二、 文件下载
2.1 对于浏览器不识别的文件,可以直接利用a链接下载
<!-- 因为他们三个浏览器不认识这样的类型 -->
<a href="./downlist/1.rar">1.rar</a>
<a href="./downlist/1.exe">1.exe</a>
<a href="./downlist/1.avi">1.avi</a>
2.2 对于浏览器不识别的,可以利用readfile函数
<!-- 浏览器人事这样的类型就会被解析 --><a href="./action.php?name=1.html">1.html</a><a href="./action.php?name=1.php">1.php</a><a href="./action.php?name=1.txt">1.txt</a><a href="./action.php?name=1.jpg">1.jpg</a>//接收一下name值
$name = $_GET['name'];//实现下载功能,强制浏览器弹出另存为对话框
header('content-Disposition:attachment;filename="'.$name.'"');
//此时只是下载了一个空文件,需要利用readfile读一遍所有的内容,便可下载。
$path = './downlist/'.$name;
readfile($path);
2.3 案例:
1、创建一个文件下载链接
首先,我们需要创建一个文件下载链接来让用户下载文件。假设我们已经有一个文件保存在uploads目录下,并命名为test.pdf。我们可以通过以下代码创建一个下载链接:
<a href="download.php?file=test.pdf">下载文件</a>
2、创建一个文件下载处理脚本
然后,我们需要创建一个名为 download.php 的PHP脚本来处理文件下载。创建一个具有以下代码的文件:
<?php$fileDir = "uploads/"; //文件保存的目录if (isset($_GET['file'])) {$filePath = $fileDir.$_GET['file']; //文件的完整路径if (file_exists($filePath)) {header("Content-Type:application/octet-stream");header("Content-Disposition:attachment;filename=".basename($filePath));header("Content-Length:".filesize($filePath)); readfile($filePath);} else {echo "文件不存在";}} ?>
以上代码首先指定了文件保存的目录,即uploads目录。在处理文件下载是,我们设置了一些响应头信息,如Content-Type、Content-Disposition-Length,然后使用 readfile 函数将文件内容输出到浏览器