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

PHP 接收文件上傳並獲取副檔名的完整實作指南

     編輯:PHP 相關知識

PHP 接收文件上傳並獲取副檔名的完整實作指南

文件上傳是 Web 開發基礎功能,本文系統梳理從 HTML 表單構建、$_FILES 結構解析、副檔名提取方法、安全驗證到存儲邏輯的完整流程。

一、HTML 表單關鍵點

<form action="upload.php" method="POST" enctype="multipart/form-data">
    <input type="hidden" name="MAX_FILE_SIZE" value="3000000">
    <input type="file" name="userfile">
    <input type="submit" value="上傳">
</form>
  • enctype="multipart/form-data":必須設置,否則文件不會上傳
  • MAX_FILE_SIZE:客戶端提示上限,服務端仍需驗證 $_FILES['userfile']['size']
  • method="POST":文件上傳只能用 POST

二、$_FILES 結構詳解

三、副檔名提取:三種方法對比

$filename = $_FILES['userfile']['name'];

// 方法 1:pathinfo() —— 最推薦,支援多點文件名
$ext = pathinfo($filename, PATHINFO_EXTENSION);  // 'jpg'

// 方法 2:strrchr + substr
$ext = substr(strrchr($filename, '.'), 1);  // 'jpg'

// 方法 3:反轉字符串取首段(舊代碼常見)
$ext = strrev(explode('.', strrev($filename))[0]);  // 'jpg'

建議:統一用 pathinfo(),再 strtolower() 標準化。

四、完整上傳處理流程

function processUpload($fileInputName, $allowedExt = ['jpg','jpeg','png','gif','pdf'], $maxSize = 2*1024*1024) {
    if (!isset($_FILES[$fileInputName]) || $_FILES[$fileInputName]['error'] !== UPLOAD_ERR_OK) {
        return ['success' => false, 'msg' => '上傳失敗或無文件'];
    }

    $file = $_FILES[$fileInputName];
    $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));

    // 1. 副檔名白名單
    if (!in_array($ext, $allowedExt)) {
        return ['success' => false, 'msg' => '不允許的文件類型'];
    }

    // 2. 文件大小
    if ($file['size'] > $maxSize) {
        return ['success' => false, 'msg' => '文件過大'];
    }

    // 3. MIME 類型二次驗證(可選,需 fileinfo 擴展)
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mime = finfo_file($finfo, $file['tmp_name']);
    finfo_close($finfo);
    $allowedMime = ['image/jpeg','image/png','image/gif','application/pdf'];
    if (!in_array($mime, $allowedMime)) {
        return ['success' => false, 'msg' => '文件內容類型不匹配'];
    }

    // 4. 生成唯一文件名:時間戳 + 隨機數 + 原副檔名
    $newName = date('YmdHis') . '_' . mt_rand(1000,9999) . '.' . $ext;
    $destDir = __DIR__ . '/uploads/';
    if (!is_dir($destDir)) mkdir($destDir, 0755, true);
    $destPath = $destDir . $newName;

    // 5. 移動文件
    if (!move_uploaded_file($file['tmp_name'], $destPath)) {
        return ['success' => false, 'msg' => '文件移動失敗'];
    }

    return ['success' => true, 'path' => $destPath, 'url' => '/uploads/' . $newName, 'ext' => $ext];
}

// 使用
$result = processUpload('userfile');
if ($result['success']) {
    echo "上傳成功:" . $result['url'];
} else {
    echo "錯誤:" . $result['msg'];
}

五、安全加固清單

  1. 禁用腳本執行權限:上傳目錄配置 Nginx/Apache 禁止 PHP 執行 location ~ \.php$ { deny all; }
  2. 文件名不信任用戶輸入:必須重命名,防止路徑遍歷、覆蓋系統文件
  3. MIME 雙重驗證:副檔名 + finfo 實際內容檢測
  4. 大小限制雙層:php.ini upload_max_filesize + 代碼邏輯驗證
  5. 隨機化存儲路徑:按日期分目錄 uploads/2023/10/15/,避免單目錄文件過多
  6. 病毒掃描:生產環境接入 ClamAV 或雲端安全 API
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
鍵名含義示例
name客戶端原始文件名photo.jpg
typeMIME 類型(瀏覽器提供,不可信)image/jpeg
size文件大小(位元組)24578
tmp_name服務端臨時存儲路徑/tmp/phpA1b2C3
error錯誤碼(0=成功,1=超過 php.ini 上限,2=超過表單 MAX_FILE_SIZE,3=部分上傳,4=無文件)0