PHP 网站文件上传存储方案
·
PHP 网站文件上传存储方案
在 PHP 网站中实现安全的文件上传和存储需要考虑多个方面,包括安全性、文件组织、性能等。以下是完整的文件上传存储解决方案:
1. 基础文件上传存储实现
上传处理脚本 (upload.php)
php
<?php
// 配置设置
$uploadConfig = [
'uploadDir' => __DIR__ . '/uploads/', // 上传目录(确保目录存在且有写入权限)
'allowedTypes' => [ // 允许的MIME类型
'image/jpeg', 'image/png', 'image/gif',
'application/pdf', 'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
],
'maxFileSize' => 5 * 1024 * 1024, // 最大文件大小(5MB)
'fileNameLength' => 32, // 随机文件名长度
'keepOriginalName' => false // 是否保留原始文件名
];
// 创建上传目录(如果不存在)
if (!file_exists($uploadConfig['uploadDir'])) {
mkdir($uploadConfig['uploadDir'], 0755, true);
}
// 处理上传
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
$file = $_FILES['file'];
// 验证上传错误
if ($file['error'] !== UPLOAD_ERR_OK) {
http_response_code(400);
die(json_encode(['error' => '上传错误: ' . $file['error']]));
}
// 验证文件大小
if ($file['size'] > $uploadConfig['maxFileSize']) {
http_response_code(400);
die(json_encode(['error' => '文件太大,最大允许 ' . ($uploadConfig['maxFileSize'] / 1024 / 1024) . 'MB']));
}
// 验证文件类型
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$detectedType = finfo_file($finfo, $file['tmp_name']);
finfo_close($finfo);
if (!in_array($detectedType, $uploadConfig['allowedTypes'])) {
http_response_code(400);
die(json_encode(['error' => '不允许的文件类型']));
}
// 生成安全文件名
$extension = pathinfo($file['name'], PATHINFO_EXTENSION);
$extension = strtolower($extension);
if ($uploadConfig['keepOriginalName']) {
// 清理原始文件名
$fileName = preg_replace('/[^a-zA-Z0-9\-_]/', '_', pathinfo($file['name'], PATHINFO_FILENAME));
$fileName = substr($fileName, 0, 50); // 限制长度
$fileName = $fileName . ($extension ? '.' . $extension : '');
} else {
// 生成随机文件名
$fileName = bin2hex(random_bytes($uploadConfig['fileNameLength'] / 2));
$fileName = substr($fileName, 0, $uploadConfig['fileNameLength']);
$fileName = $fileName . ($extension ? '.' . $extension : '');
}
// 目标路径(按日期组织文件)
$subDir = date(');
$targetDir = $uploadConfig['uploadDir'] . $subDir . '/';
if (!file_exists($targetDir)) {
mkdir($targetDir, 0755, true);
}
$targetPath = $targetDir . $fileName;
// 移动文件(使用rename避免复制开销)
if (rename($file['tmp_name'], $targetPath)) {
// 设置适当权限
chmod($targetPath, 0644);
// 返回成功响应(包含相对路径)
$relativePath = 'uploads/' . $subDir . '/' . $fileName;
echo json_encode([
'success' => true,
'filePath' => $relativePath,
'fileName' => $fileName更多推荐
所有评论(0)