<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>文件上传</title>
</head>
<body>
<h1>选择要上传的文件</h1>
<!-- 定义一个包含文件输入字段的表单 -->
<form action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="fileToUpload" id="fileToUpload">
<input type="submit" value="上传">
</form>
</body>
</html>
这个是增强版本的文件上传函数,增加了以下功能:
添加了对上传文件大小的限制。 通过指定 $allowedExtensions 参数检查上传文件的扩展名。
使用随机字符串生成新的文件名,防止目录遍历攻击。 对于图片文件,进行了基本的尺寸验证(通过 getimagesize()
函数)。若需进一步验证图像内容或处理潜在的安全风险,可以启用注释中的代码块来创建和销毁临时图像资源。
请注意,在实际生产环境中,针对图像文件的验证可能需要更复杂的逻辑,具体取决于您的需求。例如,您可以根据业务需求设定最大宽高比、最小和最大尺寸等条件。
function uploadFile($file, $uploadDir, $allowedExtensions = [], $maxFileSize = 0, $allowedMimeTypes = []) {
// 检查是否是 POST 请求以及是否有文件被上传
if (!isset($_FILES[$file]) || $_SERVER['REQUEST_METHOD'] !== 'POST') {
return ['status' => false, 'message' => 'Invalid request.'];
}
$uploadedFile = $_FILES[$file];
// 检查错误状态
if ($uploadedFile['error'] !== UPLOAD_ERR_OK) {
switch ($uploadedFile['error']) {
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
$errorMessage = 'The uploaded file exceeds the maximum allowed size.';
break;
case UPLOAD_ERR_NO_FILE:
$errorMessage = 'No file was uploaded.';
break;
default:
$errorMessage = 'Unknown error occurred while uploading file.';
}
return ['status' => false, 'message' => $errorMessage];
}
// 检查文件大小限制
if ($maxFileSize > 0 && $uploadedFile['size'] > $maxFileSize) {
return ['status' => false, 'message' => 'The uploaded file exceeds the maximum allowed size.'];
}
// 检查 MIME 类型(如果已提供允许的 MIME 类型)
if (!empty($allowedMimeTypes)) {
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($uploadedFile['tmp_name']);
if (!in_array($mime, $allowedMimeTypes)) {
return ['status' => false, 'message' => 'Invalid file type.'];
}
}
// 检查扩展名是否允许
$ext = strtolower(pathinfo($uploadedFile['name'], PATHINFO_EXTENSION));
if (!empty($allowedExtensions) && !in_array($ext, $allowedExtensions)) {
return ['status' => false, 'message' => 'Invalid file extension.'];
}
// 生成安全的唯一文件名,防止目录遍历攻击
$newFileName = bin2hex(random_bytes(16)) . '.' . $ext;
// 定义并检查目标文件夹路径是否存在且可写
$targetPath = rtrim($uploadDir, '/') . '/';
if (!is_dir($targetPath) || !is_writable($targetPath)) {
return ['status' => false, 'message' => 'Upload directory is not writable or does not exist.'];
}
// 对于图片文件进行尺寸和内容验证(假设使用GD库)
if (in_array($mime, ['image/jpeg', 'image/png', 'image/gif'])) {
$imageInfo = getimagesize($uploadedFile['tmp_name']);
if (!$imageInfo) {
return ['status' => false, 'message' => 'Invalid image file.'];
}
// 可在此处添加对图像尺寸、类型等的进一步验证
// ...
// 如果需要,可以创建一个临时图像资源以进一步验证内容
// $img = imagecreatefromstring(file_get_contents($uploadedFile['tmp_name']));
// if (!$img) {
// return ['status' => false, 'message' => 'Failed to process the image.'];
// }
// imagedestroy($img);
}
// 将文件移动到目标目录
$targetFile = $targetPath . $newFileName;
if (!move_uploaded_file($uploadedFile['tmp_name'], $targetFile)) {
return ['status' => false, 'message' => 'Failed to move uploaded file to target directory.'];
}
return [
'status' => true,
'message' => 'File uploaded successfully.',
'filename' => $newFileName,
'filepath' => $targetFile,
];
}
// 使用示例:
$uploadDir = './upload';
$allowedExtensions = ['jpg', 'jpeg', 'png'];
$maxFileSize = 5 * 1024 * 1024; // 最大文件大小为5MB
$allowedMimeTypes = ['image/jpeg', 'image/png'];
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['fileToUpload'])) {
$result = uploadFile('fileToUpload', $uploadDir, $allowedExtensions, $maxFileSize, $allowedMimeTypes);
if ($result['status']) {
echo 'File uploaded: ' . $result['filepath'];
} else {
echo 'Error: ' . $result['message'];
}
}