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

PHP 批量文件上傳完整實現:從前端到後端的安全實踐

     編輯:PHP 綜合知識

前端表單(支持多選)

<form action="upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="product_img[]" multiple accept="image/*" />
    <button type="submit" name="submit">上傳</button>
</form>

關鍵點:name="product_img[] 陣列命名、multiple 屬性、enctype="multipart/form-data"。

後端處理(upload.php)

<?php
// 配置
$uploadDir = __DIR__ . '/Public/Upload/';
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
$maxSize = 5 * 1024 * 1024; // 5MB

if (!is_dir($uploadDir)) {
    mkdir($uploadDir, 0755, true);
}

$results = ['success' => [], 'errors' => []];

if (isset($_POST['submit'])) {
    $files = $_FILES['product_img'] ?? [];
    $count = count($files['name']);
    
    for ($i = 0; $i < $count; $i++) {
        $error = $files['error'][$i];
        if ($error !== UPLOAD_ERR_OK) {
            $results['errors'][] = "文件 {$files['name'][$i]}: 錯誤代碼 $error";
            continue;
        }
        
        $tmpName = $files['tmp_name'][$i];
        $origName = basename($files['name'][$i]);
        $type = $files['type'][$i];
        $size = $files['size'][$i];
        
        // 1. 類型驗證(防偽造 MIME)
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $realType = finfo_file($finfo, $tmpName);
        finfo_close($finfo);
        if (!in_array($realType, $allowedTypes, true)) {
            $results['errors'][] = "$origName: 類型不允許 ($realType)";
            continue;
        }
        
        // 2. 大小驗證
        if ($size > $maxSize) {
            $results['errors'][] = "$origName: 超過 5MB 限制";
            continue;
        }
        
        // 3. 生成安全文件名
        $ext = strtolower(pathinfo($origName, PATHINFO_EXTENSION));
        $newName = bin2hex(random_bytes(8)) . '_' . time() . ".$ext";
        $destPath = $uploadDir . $newName;
        
        // 4. 移動文件
        if (move_uploaded_file($tmpName, $destPath)) {
            $results['success'][] = [
                'original' => $origName,
                'stored' => $newName,
                'path' => $destPath,
                'size' => $size,
                'type' => $realType
            ];
        } else {
            $results['errors'][] = "$origName: 移動失敗(權限/磁盤空間)";
        }
    }
}

header('Content-Type: application/json; charset=UTF-8');
echo json_encode($results, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
?>

安全加固清單

風險對策
腳本上傳執行上傳目錄配置 php_flag engine off / SetHandler default-handler,禁用腳本執行
文件名注入忽略原始文件名,使用隨機名 + 白名單後綴
MIME 偽造用 finfo_file 檢測真實類型,不信任 $_FILES['type']
大文件 DoS限制 upload_max_filesize、post_max_size、單文件/總大小
目錄遍歷basename()、realpath() 校驗目標路徑在允許目錄內

進階擴展

  • 分片上傳:大文件前端切片,後端合併(WebUploader/Plupload)。
  • 雲存儲直傳:簽名 URL 直傳 OSS/S3,減輕服務器帶寬。
  • 圖片處理:上傳後異步生成縮略圖、水印、WebP 轉換(Intervention Image / GD / Imagick)。
  • 資料庫記錄:保存文件元數據(用戶、業務關聯、路徑、哈希值)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved