首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 檔案上傳完整實作:表單、處理邏輯、類別封裝與安全防護

     編輯:PHP 綜合知識

1. 上傳表單 upload.php

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>檔案上傳</title>
</head>
<body>
    <form action="uploadProcess.php" method="post" enctype="multipart/form-data">
        <table>
            <tr><td>用戶名</td><td><input type="text" name="username" required></td></tr>
            <tr><td>檔案說明</td><td><textarea name="fileintro" rows="5" cols="40"></textarea></td></tr>
            <tr><td>選擇檔案</td><td><input type="file" name="myfile" required></td></tr>
            <tr><td colspan="2"><input type="submit" value="上傳"></td></tr>
        </table>
    </form>
</body>
</html>

2. 處理邏輯 uploadProcess.php

<?php
$username = $_POST['username'] ?? '';
$fileintro = $_POST['fileintro'] ?? '';

// 檔案資訊
$file = $_FILES['myfile'] ?? null;
if (!$file || $file['error'] !== UPLOAD_ERR_OK) {
    die('上傳失敗或無檔案');
}

// 限制大小 2MB
if ($file['size'] > 2 * 1024 * 1024) {
    die('檔案不得超過 2MB');
}

// 限制類型(示例僅允許 JPEG)
$allowedTypes = ['image/jpeg', 'image/pjpeg'];
if (!in_array($file['type'], $allowedTypes)) {
    die('僅允許 JPG 格式');
}

// 使用者專屬目錄
$userDir = $_SERVER['DOCUMENT_ROOT'] . '/file/up/' . $username;
if (!is_dir($userDir)) mkdir($userDir, 0755, true);

// 防重名:時間戳 + 隨機數 + 原副檔名
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
$newName = time() . '_' . mt_rand(1, 1000) . '.' . $ext;
$dest = $userDir . '/' . $newName;

// 移動檔案(中文檔名編碼轉換視伺服器環境)
if (move_uploaded_file($file['tmp_name'], $dest)) {
    echo $file['name'] . ' 上傳成功';
} else {
    echo '上傳失敗';
}
?>

3. 物件導向封裝 Upload.php

<?php
class Upload {
    public $uploadName;
    public $tmpPath;
    public $fileSize;
    public $fileType;
    public $saveRoot;
    public $allowedExt = ['jpeg','jpg','png','gif','bmp','doc','zip','rar','txt','wps','xlsx','ppt'];
    public $maxSize = 2 * 1024 * 1024;

    public function __construct($inputName = 'myfile') {
        $f = $_FILES[$inputName] ?? null;
        if (!$f || $f['error'] !== UPLOAD_ERR_OK) throw new Exception('無效上傳');
        $this->uploadName = $f['name'];
        $this->tmpPath    = $f['tmp_name'];
        $this->fileSize   = $f['size'];
        $this->fileType   = $f['type'];
        $this->saveRoot   = $_SERVER['DOCUMENT_ROOT'] . '/file/up/';
    }

    public function upload($username) {
        // 大小檢查
        if ($this->fileSize > $this->maxSize) throw new Exception('檔案過大');

        // 副檔名檢查
        $ext = $this->getExt($this->uploadName);
        if (!in_array(strtolower($ext), $this->allowedExt)) throw new Exception('副檔名不允許');

        // 使用者目錄
        $userDir = $this->saveRoot . $username;
        if (!is_dir($userDir)) mkdir($userDir, 0755, true);

        // 目的檔名
        $dest = $userDir . '/' . time() . '_' . mt_rand(1, 1000) . '.' . $ext;

        // 移動
        if (!move_uploaded_file($this->tmpPath, $dest)) throw new Exception('移動失敗');
        return $dest;
    }

    private function getExt($filename) {
        return pathinfo($filename, PATHINFO_EXTENSION);
    }
}

// 使用範例
try {
    $uploader = new Upload();
    $path = $uploader->upload($_POST['username']);
    echo '上傳成功:' . $path;
} catch (Exception $e) {
    echo '錯誤:' . $e->getMessage();
}
?>

安全防護清單

  • ✅ 檢查 $_FILES['error'] === UPLOAD_ERR_OK
  • ✅ 限制副檔名白名單(勿信任 type,易偽造)
  • ✅ 限制檔案大小
  • ✅ 重新命名(避免覆蓋、路徑遍歷、腳本執行)
  • ✅ 儲存目錄設為不可執行(Nginx/Apache 禁用 PHP 解析)
  • ✅ 圖片類可用 getimagesize() 二次驗證
  • ✅ 上傳後掃毒(ClamAV 等)
  • ✅ 記錄日誌:用戶、原始檔名、儲存路徑、IP、時間
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved