上传文件的大体思路
①需了解以下知识,部分
-修改php.ini
中file_uploads:On
,一般默认就是On
-upload_tmp_dir=
:文件上传至服务器上存储临时文件的地址
-upload_max_filesize=100m
:允许上传文件大小的最大值
-is_uploaded_file()
:判断上传文件的合法性(是否通过HTTP POST上传),注意:判断的是临时文件名
-move_uploaded_file($var1, $var2)
:将临时文件移至目标文件,第一个参数是临时文件名,第一个参数目标文件名(需带路径)
②上传文件判断的步骤
-判断文件是否上传成功
(根据error
的值判断)
-判断文件是否合法上传
(同时可判断文件类型等)
-将临时文件移至目标文件中
(注意将目标文件加密,防止重复命名,文件覆盖)
单文件上传——仅限PDF格式
以下是单文件上传代码
<?php
namespace chapter9;
use Exception;
require 'config.php';
//处理用户的文件上传,需要三步
//- 判断文件是否上传成功
//- 判断文件是否合法上传
//- 将临时文件移动到用户目录中
//var_dump($_FILES['pdf_file']['error']);
try {
// 1,判断文件是否上传成功
$error = $_FILES['pdf_file']['error'];
if ($error > UPLOAD_ERR_OK) {
switch ($error) {
case UPLOAD_ERR_INI_SIZE:
throw new Exception('上传文件超过了`php.ini`配置文件中`upload_max_filesize`的设定最大内存');
break;
case UPLOAD_ERR_FORM_SIZE:
throw new Exception('文件大小超过了HTML表单中MAX_FILE_SIZE的大小');
break;
case UPLOAD_ERR_PARTIAL:
throw new Exception('仅上传了部分文件');
break;
case UPLOAD_ERR_NO_FILE:
throw new Exception('没有文件上传');
break;
case UPLOAD_ERR_NO_TMP_DIR:
throw new Exception('找不到临时文件');
break;
case UPLOAD_ERR_CANT_WRITE:
throw new Exception('文件写入失败');
break;
default:
throw new Exception('不明了的上传错误');
}
} else {
// 判断临时文件是否合法:用临时文件名判断
// 导出临时文件
$tmp_name = $_FILES['pdf_file']['tmp_name'];
// 限制上传文件的文件类型
$type = 'pdf';
// 进行判断
if (is_uploaded_file($tmp_name) === true) {
// 获取上传文件的扩展名
$extension = pathinfo($_FILES['pdf_file']['name'])['extension'];
if ($extension === $type) {
// 创建用户文件名(目标用户目录)
$user_dir = 'userdir/' . md5($_FILES['pdf_file']['name'] . time()) . '.' . $extension;
// 移动临时文件合法则移到用户目录中去
if (move_uploaded_file($tmp_name, $user_dir)) {
echo '移动成功';
}
} else {
throw new Exception('文件上传类型不符,请按规定上传');
}
} else {
throw new Exception('非法文件上传');
}
}
} catch (Exception $e) {
echo $e->getMessage();
}
多文件上传
多文件上传大体思路跟单文件差不多,但要注意的是
-因为$_FILES
打印出来的多文件数组是根据键名
进行分类,所以在判断文件是否上传成功之前,要先对数组进行重组
以下是处理多文件上传的代码
<?php
namespace chapter9;
use Exception;
//print_r($_FILES['more_files']);
//$more_files = $_FILES['more_files'];
//die;
//echo '<hr>';
//因为上传多个文件,$_FILES所打印出来的页面是将各键名分类的,所以要将各文件的信息重新编排下
try {
// 创建一个数组容器,来装各个上传文件的内容
$more_files = [];
// 用for()循环重新遍历上传文件的信息,并将其封装到数组容器中
for ($i = 0; $i < count($_FILES['more_files']['name']); $i++) {
$more_files[] = [
'name' => $_FILES['more_files']['name'][$i],
'type' => $_FILES['more_files']['type'][$i],
'tmp_name' => $_FILES['more_files']['tmp_name'][$i],
'error' => $_FILES['more_files']['error'][$i],
'size' => $_FILES['more_files']['size'][$i]
];
}
// print_r($more_files);
// 然后用foreach()循环遍历出各个数组,重新组成新的数组
foreach ($more_files as $file) {
if ($file['error'] > UPLOAD_ERR_OK) {
switch ($file['error']) {
case UPLOAD_ERR_INI_SIZE:
throw new Exception('上传文件超过了`php.ini`配置文件中`upload_max_filesize`的设定最大内存');
case UPLOAD_ERR_FORM_SIZE:
throw new Exception('文件大小超过了HTML表单中MAX_FILE_SIZE的大小');
case UPLOAD_ERR_PARTIAL:
throw new Exception('仅上传了部分文件');
break;
case UPLOAD_ERR_NO_FILE:
throw new Exception('没有文件上传');
break;
case UPLOAD_ERR_NO_TMP_DIR:
throw new Exception('找不到临时文件');
break;
case UPLOAD_ERR_CANT_WRITE:
throw new Exception('文件写入失败');
break;
default:
throw new Exception('不明了的上传错误');
}
} else {
// 文件以没有问题,现在判断上传文件是否是通过HTTP POST合法上传
// 2,判断合法性
if (is_uploaded_file($file['tmp_name']) === true) {
// 如合法,再判断是否符合规定的文件类型,以下是规定文件类型
$type = ['jpg', 'jpeg', 'png', 'gif'];
// 获取上传文件的文档类型后缀
$extension = pathinfo($file['name'])['extension'];
// 判断是否文件类型
if (in_array($extension, $type)) {
// 如何符合类型,接着就将临时文件移动到目标文件里面去
// 获取临时文件
$tmp_file = $file['tmp_name'];
// 创建目标文件(是文件路径的形式),路径+上传文件的文件名
$user_file = 'userdir/' . md5($file['name']) . time() . '.' .$extension;
// 移动临时文件
if (move_uploaded_file($tmp_file, $user_file)){
echo '上传成功';
}
}else{throw new Exception('文件上传类型不符,请按规定上传');}
}else{throw new Exception('非法文件上传');}
}
}
// 1, 判断文件是否上传成功
} catch (Exception $e) {
echo $e->getMessage();
}
调用其他脚本的函数来处理文件上传
我的思路是直接将文件上传处理的函数的一部分,修改关键的一部分,剪切后封装到另一个脚本的函数中,如下:
这样,在处理文件上传的脚本中,只要加载此脚本,调用里面的函数就行,不知道这样对不对,往老师指出,以下代码只是判断文件是否上传成功
这部分
<?php
namespace chapter9;
use Exception;
//获取$_FILES数组里面的键名(就是HTML页面,上传文件的name属性)
function config()
{
switch ($_FILES[key($_FILES)]['error']) {
case UPLOAD_ERR_INI_SIZE:
throw new Exception('上传文件超过了`php.ini`配置文件中`upload_max_filesize`的设定最大内存');
break;
case UPLOAD_ERR_FORM_SIZE:
throw new Exception('文件大小超过了HTML表单中MAX_FILE_SIZE的大小');
break;
case UPLOAD_ERR_PARTIAL:
throw new Exception('仅上传了部分文件');
break;
case UPLOAD_ERR_NO_FILE:
throw new Exception('没有文件上传');
break;
case UPLOAD_ERR_NO_TMP_DIR:
throw new Exception('找不到临时文件');
break;
case UPLOAD_ERR_CANT_WRITE:
throw new Exception('文件写入失败');
break;
default:
throw new Exception('不明了的上传错误');
}
}
附加作业:处理单个文件上传的通用类
我的思路:既然是通用类,那不管在任何文件中都可以使用,所以就要用预定义函数来获取HTML页面中,input
代码里的name
值,所以我就要key($_FILES)
获取name
的值,替代PHP脚本的相对应的代码,以下为具体代码:
<?php
namespace chapter9;
use Exception;
class Current
{
public function config()
{
try
{
// 1,判断文件是否上传成功
if ($_FILES[key($_FILES)]['error'] > UPLOAD_ERR_OK)
{
switch ($_FILES[key($_FILES)]['error'])
{
case UPLOAD_ERR_INI_SIZE:
throw new Exception('上传文件超过了`php.ini`配置文件中`upload_max_filesize`的设定最大内存');
break;
case UPLOAD_ERR_FORM_SIZE:
throw new Exception('上传文件大小超过了HTML表单中`MAX_FILE_SIZE`规定的大小');
break;
case UPLOAD_ERR_PARTIAL:
throw new Exception('仅上传了部分文件');
break;
case UPLOAD_ERR_NO_FILE:
throw new Exception('没有文件上传');
break;
case UPLOAD_ERR_NO_TMP_DIR:
throw new Exception('找不到临时文件');
break;
case UPLOAD_ERR_CANT_WRITE:
throw new Exception('文件写入失败');
break;
default:
throw new Exception('不明了的上传错误');
}
}else {
// 判断临时文件是否合法:用临时文件名判断
// 导出临时文件
$tmp_name = $_FILES[key($_FILES)]['tmp_name'];
// 限制上传文件的文件类型
$type = ['txt', 'jpg', 'jpeg', 'gif', 'pdf'];
// 进行判断
if (is_uploaded_file($tmp_name) === true) {
// 获取上传文件的扩展名
$extension = pathinfo($_FILES[key($_FILES)]['name'])['extension'];
if (in_array($extension, $type)) {
// 创建用户文件名(目标用户目录)
$user_dir = 'userdir/' . md5($_FILES[key($_FILES)]['name'] . time()) . '.' . $extension;
// 移动临时文件合法则移到用户目录中去
if (move_uploaded_file($tmp_name, $user_dir)) {
echo '移动成功';
}
} else {
throw new Exception('文件上传类型不符,请按规定上传');
}
} else {
throw new Exception('非法文件上传');
}
}
}catch
(Exception $e){
echo $e->getMessage();
}
}
}
谢谢老师审阅!