一个可以用于生产环境得PHP上传函数

发布时间:2024年01月01日

上传表单

<!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>

PHP文件上传函数

这个是增强版本的文件上传函数,增加了以下功能:

添加了对上传文件大小的限制。 通过指定 $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'];
    }
}
文章来源:https://blog.csdn.net/qq_23488347/article/details/135322433
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。