文件上传
1. 文件上传配置
文件上传项目项在php.ini
中设置,常用的配置项有:
序号 |
配置项 |
默认值 |
描述 |
1 |
file_uploads |
On |
使 PHP 支持文件上传 |
2 |
upload_tmp_dir |
/tmp |
指示应该临时把上传的文件存储在什么位置 |
3 |
max_file_uploads |
20 |
单次请求时允许上传的最大文件数量 |
4 |
max_execution_time |
30 |
设置 PHP 最长执行时间(秒) |
5 |
max_input_time |
60 |
设置 PHP 通过 POST/GET/PUT 接收数据的时长(秒) |
6 |
memory_limit |
128M |
系统分配给当前脚本执行可用的最大内存容量 |
7 |
post_max_size |
8M |
允许的 POST 数据的总大小(以字节为单位) |
8 |
upload_max_filesize |
32M |
允许的尽可能最大的文件上传(以字节为单位) |
$_FILES
- 上传文件的描述信息,全部保存在系统全局变量
$_FILES
中 $_FILES
以二维数组形式保存: $_FILES['form_file_name']['key']
'form_file_name'
: 对应着表单中<input type="file" name="my_pic">
中name
属性值'key'
: 共有 5 个键名, 描述如下:
序号 |
键名 |
描述 |
1 |
name |
文件在客户端的原始文件名(即存在用户电脑上的文件名) |
2 |
type |
文件的 MIME 类型, 由浏览器提供, PHP 并不检查它 |
3 |
tmp_name |
文件被上传到服务器上之后,在临时目录中临时文件名 |
4 |
error |
和该文件上传相关的错误代码 |
5 |
size |
已上传文件的大小(单位为字节) |
序号 |
常量 |
值 |
描述 |
1 |
UPLOAD_ERR_OK |
0 |
没有错误发生,文件上传成功 |
2 |
UPLOAD_ERR_INI_SIZE |
1 |
文件超过php.ini 中upload_max_filesize 值 |
3 |
UPLOAD_ERR_FORM_SIZE |
2 |
文件大小超过表单中MAX_FILE_SIZE 指定的值 |
4 |
UPLOAD_ERR_PARTIAL |
3 |
文件只有部分被上传 |
5 |
UPLOAD_ERR_NO_FILE |
4 |
没有文件被上传 |
6 |
UPLOAD_ERR_NO_TMP_DIR |
6 |
找不到临时文件夹 |
7 |
UPLOAD_ERR_CANT_WRITE |
7 |
文件写入失败 |
序号 |
属性设置 |
描述 |
1 |
<form method="POST"> |
请求类型必须是POST |
2 |
<form enctype="multipart/form-data"> |
设置表单提交数据的编码类型 |
3 |
<input type="file" name="uploads"> |
设置表单控件类型与名称以支持上传 |
4 |
<input type="hidden" name="MAX_FILE_SIZE" value="..."> |
设置隐藏域限制上传文件大小(可选) |
enctype
: 设置表单数据,在发送到服务器之前的编码规则
序号 |
属性值 |
描述 |
1 |
application/x-www-form-urlencoded |
默认值, 发送前进行编码,空格转+ ,非空字符转 16 进制 |
2 |
multipart/form-data |
不对字符编码,以二进制发送,适合文件上传 |
3 |
text/plain |
纯文本发送,仅对空格编码(转为+ ) |
4. MIME 类型
4.1 概述
- MIME: (Multipurpose Internet Mail Extensions)的简写,中文意思”多功能因特网邮件扩展”
- MIME: 最初用来表示
Email
附件格式的字符串, 后来演变成为网络文档或应用程序的文档格式规范 - MIME: 由一个媒体类型一个子类组成, 中间用斜线
/
分隔,例如text/css
4.2 类型
序号 |
类型 |
描述 |
示例 |
1 |
text |
文本 |
text/plain ,text/html ,text/css ,text/javascript |
2 |
image |
图像 1 |
image/jpeg ,image/gif ,image/png ,image/bmp ,image/ webp , |
2 |
image |
图像 2 |
image/x-icon , image/vnd.microsoft.icon |
3 |
audio |
音频 |
audio/midi , audio/mpeg , audio/webm , audio/ogg , audio/wav |
4 |
video |
视频 |
video/mp4 ,video/mpeg ,video/webm , video/ogg ,video/x-msvideo |
5 |
application |
二进制 1 |
application/octet-stream , application/javascript , application/ecmascript |
5 |
application |
二进制 2 |
application/json ,application/pkcs12 , application/vnd.mspowerpoint |
5 |
application |
二进制 3 |
application/xhtml+xml , application/xml , application/pdf ,application/x-gzip |
- 表中,以
x-
为前缀的是还没有成为国际标准的格式 如果某个文档不在该列表中,会识别为: applicaton/octet-stream
, 如.md
文档, 尽管它是纯文本
单文件上传
<?php
class UploadException extends Exception
{
public function __toString()
{
return '错误代码:'.$this->code.'错误信息:'.$this->message;
}
}
try{
$errorcode = $_FILES['my_pic']['error'];
if ($errorcode > 0){
switch ($errorcode) {
case UPLOAD_ERR_INI_SIZE:
throw new UploadException('文件超过`php.ini`中`upload_max_filesize`值',1);
break;
case UPLOAD_ERR_FORM_SIZE:
throw new UploadException('文件大小超过表单中`MAX_FILE_SIZE`指定的值',2);
break;
case UPLOAD_ERR_PARTIAL:
throw new UploadException('文件只有部分被上传',3);
break;
case UPLOAD_ERR_NO_FILE:
throw new UploadException('没有文件被上传',4);
break;
case UPLOAD_ERR_NO_TMP_DIR:
throw new UploadException('找不到临时文件夹',6);
break;
case UPLOAD_ERR_CANT_WRITE:
throw new UploadException('文件写入失败',7);
break;
// default:
// throw new UploadException('未知错误',8);
// break;
}
}
//检测文件类型
$files_type = $_FILES['my_pic']['type'];
if (strstr($files_type,'/',true) !== 'image'){
throw new UploadException('文件类型错误',9);
}else{
//移动文件到指定目录
//先判断文件是否是通过POST上传使用is_uploaded_file
//临时文件名
$tmpFileName = $_FILES['my_pic']['tmp_name'];
//原始文件名
$originalFileName = $_FILES['my_pic']['name'];
$destFile ='uploads/'.sha1(mt_rand(10,500).time().$originalFileName);
if(is_uploaded_file($tmpFileName)){
if(move_uploaded_file($tmpFileName,$destFile)){
echo "{$originalFileName}.文件上传成功";
echo "<img src='{$destFile}' width='200'>";
}
}
}
}catch(UploadException $e){
echo $e;
}
?>
html部分
<form action="" method="POST" enctype="multipart/form-data">
<fieldset>
<legend>单文件上传</legend>
<input type="file" name="my_pic">
<button>上传</button>
</fieldset>
</form>
多文件上传
class UploadException extends Exception
{
public function __toString()
{
return '错误代码:'.$this->code.'错误信息:'.$this->message;
}
}
try{
foreach($_FILES as $file){
$errorcode = $file['error'];
if ($errorcode > 0){
switch ($errorcode) {
case UPLOAD_ERR_INI_SIZE:
throw new UploadException('文件超过`php.ini`中`upload_max_filesize`值',1);
break;
case UPLOAD_ERR_FORM_SIZE:
throw new UploadException('文件大小超过表单中`MAX_FILE_SIZE`指定的值',2);
break;
case UPLOAD_ERR_PARTIAL:
throw new UploadException('文件只有部分被上传',3);
break;
case UPLOAD_ERR_NO_FILE:
throw new UploadException('没有文件被上传',4);
break;
case UPLOAD_ERR_NO_TMP_DIR:
throw new UploadException('找不到临时文件夹',6);
break;
case UPLOAD_ERR_CANT_WRITE:
throw new UploadException('文件写入失败',7);
break;
// default:
// throw new UploadException('未知错误',8);
// break;
}
}
//检测文件类型
$files_type = $file['type'];
if (strstr($files_type,'/',true) !== 'image'){
throw new UploadException('文件类型错误',9);
}else{
//移动文件到指定目录
//先判断文件是否是通过POST上传使用is_uploaded_file
//临时文件名
$tmpFileName = $file['tmp_name'];
//原始文件名
$originalFileName = $file['name'];
$destFile ='uploads/'.sha1(mt_rand(10,500).time().$originalFileName);
if(is_uploaded_file($tmpFileName)){
if(move_uploaded_file($tmpFileName,$destFile)){
echo "{$originalFileName}.文件上传成功";
echo "<img src='{$destFile}' width='200'>";
}
}
}
}
}catch(UploadException $e){
echo $e;
}
//html部分
<form action="" method="POST" enctype="multipart/form-data">
<fieldset>
<legend>多文件上传</legend>
<input type="file" name="my_pic1">
<input type="file" name="my_pic2">
<input type="file" name="my_pic3">
<button>上传</button>
</fieldset>
</form>
批量上传
class UploadException extends Exception
{
public function __toString()
{
return '错误代码:'.$this->code.'错误信息:'.$this->message;
}
}
try{
if($_FILES['my_pic']){
foreach($_FILES['my_pic']['error'] as $key=>$error){
if ($error > 0){
switch ($error) {
case UPLOAD_ERR_INI_SIZE:
throw new UploadException('文件超过`php.ini`中`upload_max_filesize`值',1);
break;
case UPLOAD_ERR_FORM_SIZE:
throw new UploadException('文件大小超过表单中`MAX_FILE_SIZE`指定的值',2);
break;
case UPLOAD_ERR_PARTIAL:
throw new UploadException('文件只有部分被上传',3);
break;
case UPLOAD_ERR_NO_FILE:
throw new UploadException('没有文件被上传',4);
break;
case UPLOAD_ERR_NO_TMP_DIR:
throw new UploadException('找不到临时文件夹',6);
break;
case UPLOAD_ERR_CANT_WRITE:
throw new UploadException('文件写入失败',7);
break;
// default:
// throw new UploadException('未知错误',8);
// break;
}
}
//检测文件类型
$files_type = $_FILES['my_pic']['type'][$key];
if (strstr($files_type,'/',true) !== 'image'){
throw new UploadException('文件类型错误',9);
}else{
//移动文件到指定目录
//先判断文件是否是通过POST上传使用is_uploaded_file
//临时文件名
$tmpFileName = $_FILES['my_pic']['tmp_name'][$key];
//原始文件名
$originalFileName = $_FILES['my_pic']['name'][$key];
$destFile ='uploads/'.sha1(mt_rand(10,500).time().$originalFileName);
if(is_uploaded_file($tmpFileName)){
if(move_uploaded_file($tmpFileName,$destFile)){
echo "{$originalFileName}.文件上传成功";
echo "<img src='{$destFile}' width='200'>";
}
}
}
}
}
}catch(UploadException $e){
echo $e;
}
//html部分
<form action="" method="POST" enctype="multipart/form-data">
<fieldset>
<legend>批量上传</legend>
<!-- multiple属性:批量上传 -->
<input type="file" name="my_pic[]" multiple>
<button>上传</button>
</fieldset>
</form>
总结
文本上传一定要记住$_FILES的5个键名name,tmp_name,type,size,error以及error的值代表的意思,移动文件的move_uploaded_file函数,判断文件是否是通过post上传的is_uploaded_file函数,以及上传的一系列检测。