一、文件上传
文件上传的基础知识:
- 首先,在客户端form表达设置,选择上传的文件
- 然后,在服务器对上传文件进行操作处理
1.1 关于前台页面
必须设置 form 表单项:
html
<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程序
通过PHP脚本来处理的,具体需要通过以下三个方面信息
后端的PHP文件,是基于一个数组来接收传入的文件的,这个数组是一个内置数组【二维数组】:
html$_FILES
数组的索引值
html注意: html的input标签的name的值是myfile $_FILES["myfile"]["error"]: 记录文件上传过程中,是否发生了错误,如果这里的值大于0,那么就发生了错误:否则上传成功 $_FILES["myfile"]["name"]: 上传的文件名称 $_FILES["myfile"]["tmp_name"]: 文件被上传到服务器后,文件在服务器上的文件名 $_FILES["myfile"]["type"]: 上传文件的文件类型 $_FILES["myfile"]["size"]: 上传文件的大小,默认单位是字节
1.3 php的文件上传处理函数
上传成功的文件会被放置到服务器端临时目录下,文件名是随机生成的临时文件名。
注:该文件在程序执行完后将自动删除掉。在删除前可以像本地文件一样操作。
文件上传处理函数:
phpis_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:如果目标文件已经存在,将会被覆盖。
案例:
前台页面
html
<!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>
后台程序
php
<?php
header("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 文件上传的错误代码:
php
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、设置前端上传界面
php<from action="upload.php" method="post" enctype="multipart/form-data"> <input type="file" name="myfile"> <input type="submit" value="上传"> </from>
2、upload.php 处理上传到临时目录的文件
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>"; } ?> ==================================================================================== <?php if ($_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"]' } } ?>
封装成函数:
思路
phpfunction upload(){ //1.判读文件是否上传错误 //2.判断文件上传的类型是否是你想要的类型 //3.起名字 //4.判断保存路径是否存在 //5.判断是否是http post方式上传 //6.移动图片 //7.返回移动成功的图片名 }
开始封装函数:新建 function php
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; } ?>
调用函数开始上传:
php<?php include './function.php'; echo upload('file','./leiding',array('jpg','png'));
参考版本
php
<?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目录权限为777
if (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、使用不同的表单元素
php<input type="file" name="file_a"> <input type="file" name="file_b"> <input type="file" name="file_c">
2、使用数组格式的表单元素
php<input type="file" name="file[]"> <input type="file" name="file[]"> <input type="file" name="file[]">
二、 文件下载
2.1 对于浏览器不识别的文件,可以直接利用a链接下载
php
<!-- 因为他们三个浏览器不认识这样的类型 -->
<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函数
php
<!-- 浏览器人事这样的类型就会被解析 -->
<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。我们可以通过以下代码创建一个下载链接:
html<a href="download.php?file=test.pdf">下载文件</a>
2、创建一个文件下载处理脚本
然后,我们需要创建一个名为 download.php 的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 函数将文件内容输出到浏览器