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

PHP 檔案上傳失效完整排查清單

     編輯:PHP 綜合知識

快速診斷流程

  1. 檢查 $_FILES['file']['error'] 錯誤碼
  2. 驗證 php.ini 關鍵設定
  3. 確認目錄權限與擁有者
  4. 檢查 Web Server (Nginx/Apache) 客戶端上傳體積限制
  5. 排查防火牆/安全模組 (ModSecurity, SELinux)

錯誤碼對照表

錯誤碼常數原因解決方向
0UPLOAD_ERR_OK成功—
1UPLOAD_ERR_INI_SIZE超過 upload_max_filesize調大 php.ini 設定
2UPLOAD_ERR_FORM_SIZE超過表單 MAX_FILE_SIZE移除或調大 hidden input
3UPLOAD_ERR_PARTIAL上傳中斷檢查網路/逾時/體積限制
4UPLOAD_ERR_NO_FILE未選檔案前端驗證
6UPLOAD_ERR_NO_TMP_DIR缺臨時目錄設定 upload_tmp_dir
7UPLOAD_ERR_CANT_WRITE寫入失敗權限/磁碟空間
8UPLOAD_ERR_EXTENSION擴充套件攔截檢查 suhosin 等

php.ini 關鍵設定 (必檢項目)

; ====== 必須開啟 ======
file_uploads = On

; ====== 體積限制 (建議值,視需求調整) ======
upload_max_filesize = 50M          ; 單檔上限
post_max_size = 60M                ; 必須 > upload_max_filesize
memory_limit = 256M                ; 建議 > post_max_size

; ====== 臨時目錄 (需存在且可寫) ======
upload_tmp_dir = "/var/tmp/php_upload"
; 若註解掉則使用系統預設 /tmp

; ====== 執行時間 (大檔上傳需較長) ======
max_execution_time = 300           ; 5 分鐘
max_input_time = 300               ; 接收資料時間

; ====== 安全相關 ======
; suhosin.upload.max_uploads = 25  ; 若裝 suhosin 需調整
; suhosin.post.max_value_length = 10000000

目錄權限檢查腳本

<?php
// check_upload_perms.php
$dirs = [
    ini_get('upload_tmp_dir') ?: sys_get_temp_dir(),
    __DIR__ . '/uploads',  // 你的實際上傳目錄
];

foreach ($dirs as $dir) {
    echo "目錄: $dir\n";
    echo "  存在: " . (is_dir($dir) ? '是' : '否') . "\n";
    echo "  可讀: " . (is_readable($dir) ? '是' : '否') . "\n";
    echo "  可寫: " . (is_writable($dir) ? '是' : '否') . "\n";
    echo "  擁有者: " . posix_getpwuid(fileowner($dir))['name'] . "\n";
    echo "  當前使用者: " . get_current_user() . "\n";
    echo "  PHP 使用者: " . exec('whoami') . "\n";
    echo "---\n";
}
?>

Web Server 額外限制

Nginx

# /etc/nginx/nginx.conf 或 site conf
http {
    client_max_body_size 60M;  # 必須 ≥ post_max_size
    client_body_timeout 300s;
    client_body_buffer_size 128k;
}

Apache (mod_security / LimitRequestBody)

# .htaccess 或 httpd.conf
LimitRequestBody 62914560  # 60MB (bytes)
# 或關閉 mod_security 對上傳的檢查
SecRequestBodyAccess Off

常見坑點彙總

現象真相修正
小檔正常、大檔失敗Nginx client_max_body_size 預設 1M設定足夠大小並 reload
上傳 0 bytesupload_tmp_dir 不可寫或磁碟滿檢查 df -h、權限、inode
中文檔名亂碼/失敗檔案系統/編碼/權限儲存時用 UUID 重命名,資料庫存原名
多檔上傳部分失敗max_file_uploads 預設 20php.ini 調大
$_FILES 為空表單缺 enctype="multipart/form-data"補上 enctype
SELinux 拒絕寫入audit.log 有 AVC deniedsetsebool -P httpd_unified 1 或調整 context

最佳實踐模板

<?php
function handleUpload(array $file, string $targetDir, array $allowedMimes = []): array
{
    // 1. 錯誤碼檢查
    if ($file['error'] !== UPLOAD_ERR_OK) {
        throw new RuntimeException('上傳錯誤碼: ' . $file['error']);
    }

    // 2. MIME 驗證 (不要信任副檔名)
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $mime = $finfo->file($file['tmp_name']);
    if ($allowedMimes && !in_array($mime, $allowedMimes, true)) {
        throw new RuntimeException("不允許的檔案類型: $mime");
    }

    // 3. 安全檔名
    $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
    $safeName = bin2hex(random_bytes(16)) . ($ext ? '.' . $ext : '');

    // 4. 確保目錄存在
    if (!is_dir($targetDir)) {
        mkdir($targetDir, 0755, true);
    }

    $targetPath = $targetDir . '/' . $safeName;

    // 5. 移動檔案 (跨分區自動複製+刪除)
    if (!move_uploaded_file($file['tmp_name'], $targetPath)) {
        throw new RuntimeException('移動上傳檔案失敗');
    }

    // 6. 設定安全權限 (不可執行)
    chmod($targetPath, 0644);

    return [
        'original_name' => $file['name'],
        'stored_name'   => $safeName,
        'path'          => $targetPath,
        'size'          => $file['size'],
        'mime'          => $mime,
    ];
}

// 使用
try {
    $result = handleUpload($_FILES['avatar'], '/var/www/uploads/avatars', [
        'image/jpeg', 'image/png', 'image/webp'
    ]);
    echo json_encode(['success' => true, 'data' => $result]);
} catch (Throwable $e) {
    http_response_code(400);
    echo json_encode(['success' => false, 'message' => $e->getMessage()]);
}
?>
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved