本文目录导读:

在PHP中限制文件上传大小,需要在多个层面进行配置,以下是完整的解决方案:
PHP配置层面(最核心)
php.ini 配置
; 单个上传文件的最大大小 upload_max_filesize = 10M ; POST数据最大大小(通常要比upload_max_filesize大) post_max_size = 12M ; 允许的最大上传文件数量 max_file_uploads = 20 ; 脚本执行时间(秒) max_execution_time = 300 ; 内存限制 memory_limit = 128M
通过 .htaccess 配置(Apache)
# 限制文件上传大小为10MB php_value upload_max_filesize 10M php_value post_max_size 12M php_value max_execution_time 300 php_value memory_limit 128M
通过代码动态设置
// 在脚本开头设置
ini_set('upload_max_filesize', '10M');
ini_set('post_max_size', '12M');
ini_set('max_execution_time', 300);
ini_set('memory_limit', '128M');
代码层面验证(前端+后端)
HTML表单限制
<form action="upload.php" method="post" enctype="multipart/form-data">
<!-- PHP预定义隐藏字段,必须在其他表单字段之前 -->
<input type="hidden" name="MAX_FILE_SIZE" value="10485760" />
<input type="file" name="file" />
<input type="submit" value="上传" />
</form>
后端PHP验证
<?php
// 定义上传限制
define('MAX_FILE_SIZE', 10 * 1024 * 1024); // 10MB
define('ALLOWED_TYPES', ['jpg', 'jpeg', 'png', 'gif', 'pdf']);
define('UPLOAD_PATH', './uploads/');
// 检查是否有文件上传
if (!isset($_FILES['file'])) {
die('没有文件被上传');
}
$file = $_FILES['file'];
// 错误检查
if ($file['error'] !== UPLOAD_ERR_OK) {
$errorMessages = [
UPLOAD_ERR_INI_SIZE => '文件大小超过PHP配置限制',
UPLOAD_ERR_FORM_SIZE => '文件大小超过表单MAX_FILE_SIZE限制',
UPLOAD_ERR_PARTIAL => '文件只上传了一部分',
UPLOAD_ERR_NO_FILE => '没有文件被上传',
UPLOAD_ERR_NO_TMP_DIR => '找不到临时文件夹',
UPLOAD_ERR_CANT_WRITE => '文件写入失败',
UPLOAD_ERR_EXTENSION => '文件上传被扩展阻止'
];
$errorCode = $file['error'];
if (isset($errorMessages[$errorCode])) {
die($errorMessages[$errorCode]);
} else {
die('未知错误');
}
}
// 文件大小验证(双保险)
if ($file['size'] > MAX_FILE_SIZE) {
die('文件大小超过10MB限制');
}
// 检查文件类型
$fileExtension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if (!in_array($fileExtension, ALLOWED_TYPES)) {
die('文件类型不允许');
}
// 检查文件MIME类型
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $file['tmp_name']);
finfo_close($finfo);
$allowedMimes = [
'image/jpeg' => 'jpg',
'image/png' => 'png',
'image/gif' => 'gif',
'application/pdf' => 'pdf'
];
if (!array_key_exists($mimeType, $allowedMimes)) {
die('文件MIME类型不允许');
}
// 安全检查 - 避免文件类型伪造
if ($allowedMimes[$mimeType] !== $fileExtension) {
die('文件扩展名与实际类型不匹配');
}
// 生成唯一文件名
$newFileName = uniqid('upload_', true) . '.' . $fileExtension;
// 确保上传目录存在
if (!is_dir(UPLOAD_PATH)) {
mkdir(UPLOAD_PATH, 0755, true);
}
// 移动上传文件
$uploadPath = UPLOAD_PATH . $newFileName;
if (move_uploaded_file($file['tmp_name'], $uploadPath)) {
echo "文件上传成功!保存为:{$newFileName}";
echo "文件大小:" . formatFileSize($file['size']) . "<br>";
echo "文件类型:" . $mimeType . "<br>";
} else {
die('文件移动失败');
}
// 辅助函数
function formatFileSize($bytes) {
if ($bytes >= 1073741824) {
return number_format($bytes / 1073741824, 2) . ' GB';
} elseif ($bytes >= 1048576) {
return number_format($bytes / 1048576, 2) . ' MB';
} elseif ($bytes >= 1024) {
return number_format($bytes / 1024, 2) . ' KB';
} else {
return $bytes . ' 字节';
}
}
?>
前端实时验证(JavaScript)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">文件上传</title>
<style>
.error { color: red; }
.success { color: green; }
</style>
</head>
<body>
<form id="uploadForm" action="upload.php" method="post" enctype="multipart/form-data">
<h3>文件上传(最大10MB)</h3>
<div>
<label>选择文件:</label>
<input type="file" name="file" id="fileInput" accept=".jpg,.jpeg,.png,.gif,.pdf">
</div>
<div>
<span id="fileInfo"></span>
</div>
<button type="submit">上传</button>
</form>
<script>
const MAX_SIZE = 10 * 1024 * 1024; // 10MB
const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'application/pdf'];
document.getElementById('fileInput').addEventListener('change', function(e) {
const file = this.files[0];
const fileInfo = document.getElementById('fileInfo');
if (!file) {
fileInfo.textContent = '';
return;
}
// 检查大小
if (file.size > MAX_SIZE) {
fileInfo.textContent = `错误:文件大小 ${formatBytes(file.size)} 超过10MB限制`;
fileInfo.className = 'error';
this.value = ''; // 清空选择
return;
}
// 检查类型
if (!ALLOWED_TYPES.includes(file.type)) {
fileInfo.textContent = '错误:不支持的文件类型';
fileInfo.className = 'error';
this.value = '';
return;
}
// 显示文件信息
fileInfo.textContent = `文件名:${file.name},大小:${formatBytes(file.size)},类型:${file.type}`;
fileInfo.className = 'success';
});
function formatBytes(bytes) {
if (bytes >= 1048576) {
return (bytes / 1048576).toFixed(2) + ' MB';
} else if (bytes >= 1024) {
return (bytes / 1024).toFixed(2) + ' KB';
} else {
return bytes + ' 字节';
}
}
// 表单提交验证
document.getElementById('uploadForm').addEventListener('submit', function(e) {
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
if (!file) {
e.preventDefault();
alert('请选择文件');
return;
}
if (file.size > MAX_SIZE) {
e.preventDefault();
alert('文件大小超过10MB限制');
return;
}
});
</script>
</body>
</html>
Nginx配置限制(如果使用Nginx)
# 在server或location块中设置
location /upload/ {
# 限制请求体大小
client_max_body_size 10m;
# 限制上传超时时间
client_body_timeout 60s;
}
服务端汇总检查Code
<?php
class FileUploadValidator {
private $maxSize;
private $allowedExtensions;
private $allowedMimeTypes;
public function __construct($maxSize = 10485760, $allowedExtensions = [], $allowedMimeTypes = []) {
$this->maxSize = $maxSize;
$this->allowedExtensions = $allowedExtensions;
$this->allowedMimeTypes = $allowedMimeTypes;
}
public function validate($file) {
$errors = [];
// 检查是否有错误
if ($file['error'] !== UPLOAD_ERR_OK) {
$errors[] = $this->getUploadErrorMessage($file['error']);
return $errors;
}
// 检查大小
if ($file['size'] > $this->maxSize) {
$errors[] = '文件大小超过限制';
}
// 检查扩展名
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if (!empty($this->allowedExtensions) && !in_array($ext, $this->allowedExtensions)) {
$errors[] = '不允许的文件扩展名:' . $ext;
}
// 检查MIME类型
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->file($file['tmp_name']);
if (!empty($this->allowedMimeTypes) && !in_array($mimeType, $this->allowedMimeTypes)) {
$errors[] = '不允许的MIME类型:' . $mimeType;
}
return $errors;
}
private function getUploadErrorMessage($errorCode) {
$messages = [
UPLOAD_ERR_INI_SIZE => '文件大小超过PHP配置限制',
UPLOAD_ERR_FORM_SIZE => '文件大小超过表单限制',
UPLOAD_ERR_PARTIAL => '文件只上传了一部分',
UPLOAD_ERR_NO_FILE => '没有文件被上传',
UPLOAD_ERR_NO_TMP_DIR => '找不到临时文件夹',
UPLOAD_ERR_CANT_WRITE => '文件写入失败',
UPLOAD_ERR_EXTENSION => '文件上传被扩展阻止'
];
return isset($messages[$errorCode]) ? $messages[$errorCode] : '未知错误';
}
}
?>
⚠️ 注意事项
-
多层限制的重要性:不要只依赖单层限制,前端限制是用户体验,后端限制是安全保证。
-
配置调整:
post_max_size必须大于upload_max_filesize- 如果上传多个文件,要考虑总大小
- 内存限制不能小于上传文件大小
-
安全建议:
- 不要信任前端限制
- 始终在服务端进行二次验证
- 检查文件内容的MIME类型,不要只检查扩展名
- 将文件存储在Web根目录之外
- 生成随机文件名,避免路径注入
-
查看当前配置:
<?php // 查看当前PHP上传配置 echo 'upload_max_filesize: ' . ini_get('upload_max_filesize') . "<br>"; echo 'post_max_size: ' . ini_get('post_max_size') . "<br>"; echo 'max_file_uploads: ' . ini_get('max_file_uploads') . "<br>"; echo 'max_execution_time: ' . ini_get('max_execution_time') . "秒<br>"; echo 'memory_limit: ' . ini_get('memory_limit') . "<br>"; ?>
是多层文件上传大小限制的完整解决方案,应该能覆盖大部分场景需求。