通过PHP,用户可以把文件上传到服务器。文件上传可以分为单个文件上传、多个文件上传和批量上传。
一、单个文件上传
<?php
//$_FILES
printf('<pre>%s</pre>',print_r($_FILES,true));
$errorCode=$_FILES['my_pic']['error'];
// 检查是否有文件被上传
if(UPLOAD_ERR_NO_FILE === $errorCode) echo '<p>没有文件被上传</p>';
foreach ($_FILES as $file) {
// 只要判断 error === 0
if ($file['error'] === 0) {
$destFile = 'uploads/' . $file['name'];
move_uploaded_file($file['tmp_name'], $destFile);
echo "<img src='{$destFile}' width='200'>";
}
}
//检测当前文件是否是通过HTTP POST方式上传的
// $tmpFileName = $_FILES['my_pic']['tmp_name'];
// $orginalFileName = $_FILES['my_pic']['name'];
// if (is_uploaded_file($tmpFileName)) echo "{$orginalFileName}:上传方式合法";
//检测文件类型
//$fileType = $_FILES['my_pic']['type'];
//echo $fileType,'<br>';
//if (strstr($fileType,'/',true) !== 'image') echo '<p>文件类型错误</p>';
//检测上传文件的大小
echo ini_get('upload_max_filesize');
$errorCode = $_FILES['my_pic']['error'] ?? 'null';
switch ($errorCode) {
case 1:
echo '文件超过`php.ini`中`upload_max_filesize`值';
break;
case 2:
echo '文件大小超过表单隐藏域中`MAX_FILE_SIZE`指定的值';
}
//文件上传异常处理
class UploadException extends Exception
{
// 在异常子类中,可以访问并重写Exception中的四个属性,通过__toString()格式化异常输出信息
public function __toString()
{
return <<< UPLOAD
<style>
table {border-collapse: collapse;border:1px solid black;text-align: center;}
td {border:1px solid black;padding: 5px;}
tr:first-of-type {background-color:#eee;}
tr:last-of-type td {color: coral;}
</style>
<table>
<tr><td>代码</td><td>信息</td><td>文件</td><td>行号</td></tr>
<tr><td>$this->code</td><td>$this->message</td><td>$this->file</td><td>$this->line</td></tr>
</table>
UPLOAD;
}
}
///////////////////////////////////////////////////////////////////////
try {
// 上传出错的代码
$errorCode = $_FILES['my_pic']['error'];
if ($errorCode > UPLOAD_ERR_OK) {
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('上传文件的大小超过了 HTML 表单中 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:
// 测试时建议关掉default: 避免误报影响
throw new UploadException('未知类型错误', 8);
}
}
// 判断文件类型
$fileType = $_FILES['my_pic']['type'];
if (strstr($fileType, '/', true) !== 'image') throw new UploadException('文件类型错误',9);
} catch (UploadException $e) {
echo $e;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件上传变量$_FILES</title>
</head>
<body>
<!-- 上传文件时通常会写一个表单 -->
<form action="" method="POST" enctype="multipart/form-data">
<fieldset>
<legend>单文件上传</legend>
<input type="hidden" name="MAX_FILE_SIZE" value="500000">
<input type="file" name="my_pic">
<button>上传</button>
</fieldset>
</form>
</body>
</html>
输出效果:
二、多个文件上传
<?php
// $_FILES
printf('<pre>%s</pre>', print_r($_FILES, true));
//文件上传异常处理
class UploadException extends Exception
{
// 在异常子类中,可以访问并重写Exception中的四个属性,通过__toString()格式化异常输出信息
public function __toString()
{
return <<< UPLOAD
<style>
table {border-collapse: collapse;border:1px solid black;text-align: center;}
td {border:1px solid black;padding: 5px;}
tr:first-of-type {background-color:#eee;}
tr:last-of-type td {color: coral;}
</style>
<table>
<tr><td>代码</td><td>信息</td><td>文件</td><td>行号</td></tr>
<tr><td>$this->code</td><td>$this->message</td><td>$this->file</td><td>$this->line</td></tr>
</table>
UPLOAD;
}
}
///////////////////////////////////////////////////////////////////////
try {
// 上传出错的代码
$errorCode = $_FILES['my_pic']['error'];
if ($errorCode > UPLOAD_ERR_OK) {
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('上传文件的大小超过了 HTML 表单中 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:
// 测试时建议关掉default: 避免误报影响
throw new UploadException('未知类型错误', 8);
}
}
// 判断文件类型
$fileType = $_FILES['my_pic']['type'];
if (strstr($fileType, '/', true) !== 'image') throw new UploadException('文件类型错误',9);
} catch (UploadException $e) {
echo $e;
}
foreach ($_FILES as $file) {
if ($file['error'] === 0) {
$destFile = 'uploads/' . $file['name'];
move_uploaded_file($file['tmp_name'], $destFile);
echo "<img src='{$destFile}' width='200'>";
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件上传变量$_FILES</title>
</head>
<body>
<hr>
<form action="" method="POST" enctype="multipart/form-data">
<fieldset>
<legend>多文件上传: 逐个上传(一)</legend>
<input type="hidden" name="MAX_FILE_SIZE" value="3000000">
<input type="file" name="my_pic1">
<input type="file" name="my_pic2">
<input type="file" name="my_pic3">
<button>上传</button>
</fieldset>
</form>
</body>
</html>
输出效果:
三、批量上传文件
printf('<pre>%s</pre>', print_r($_FILES, true));
//文件上传异常处理
class UploadException extends Exception
{
public function __toString()
{
return <<< UPLOAD
<style>
table {border-collapse: collapse;border:1px solid black;text-align: center;}
td {border:1px solid black;padding: 5px;}
tr:first-of-type {background-color:#eee;}
tr:last-of-type td {color: coral;}
</style>
<table>
<tr><td>代码</td><td>信息</td><td>文件</td><td>行号</td></tr>
<tr><td>$this->code</td><td>$this->message</td><td>$this->file</td><td>$this->line</td></tr>
</table>
UPLOAD;
}
}
///////////////////////////////////////////////////////////////////////
try {
// 上传出错的代码
$errorCode = $_FILES['my_pic']['error'];
if ($errorCode > UPLOAD_ERR_OK) {
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('上传文件的大小超过了 HTML 表单中 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);
}
}
// 判断文件类型
$fileType = $_FILES['my_pic']['type'];
if (strstr($fileType, '/', true) !== 'image') throw new UploadException('文件类型错误',9);
} catch (UploadException $e) {
echo $e;
}
if ($_FILES['my_pic'])
foreach ($_FILES['my_pic']['error'] as $key => $error) {
// 只要判断 error === 0
if ($error === UPLOAD_ERR_OK) {
// 临时文件名
$tmpFileName = $_FILES['my_pic']['tmp_name'][$key];
// 原始文件名
$originalFileName = $_FILES['my_pic']['name'][$key];
// 目标文件名
$destFileName = 'uploads/'. $originalFileName;
// 移动文件
move_uploaded_file($tmpFileName, $destFileName);
// 预览
echo "<img src='{$destFileName}' width='200'>";
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件上传变量$_FILES</title>
</head>
<body>
<hr>
<form action="" method="POST" enctype="multipart/form-data">
<fieldset>
<legend>多文件上传: 批量上传</legend>
<input type="hidden" name="MAX_FILE_SIZE" value="3000000">
<!-- 将name属性值以数组的形式提供 -->
<input type="file" name="my_pic[]" multiple>
<button>上传</button>
</fieldset>
</form>
</body>
</html>
输出效果:
四、总结
1.允许用户上传文件对于网站来说存在着巨大的安全风险,所以只能允许可信的用户执行文件上传操作。
2.上传文件时,会在服务器的 PHP 临时文件夹创建一个被上传文件的临时副本。这个临时的复制文件会在脚本结束时消失,所以要保存被上传的文件,我们需要把它拷贝到另外的位置。示例中,我们把文件保存到了名为 “upload” 的新文件夹。