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

CodeIgniter 修復 RAR/ZIP 上傳失敗:MIME 類型配置全解析

     編輯:PHP 相關知識

問題根因

CodeIgniter 的文件上傳類通過 application/config/mimes.php 白名單驗證 MIME 類型。默認配置:

  • zip:僅包含 application/zip、application/x-zip-compressed,缺少瀏覽器常發送的 application/octet-stream、application/x-zip。
  • rar:完全缺失,導致任何 RAR 文件被拒絕。

解決方案:擴展 mimes.php

<?php
// application/config/mimes.php
return [
    // ... 現有配置保持不變 ...

    'zip' => [
        'application/zip',
        'application/x-zip',
        'application/x-zip-compressed',
        'application/octet-stream', // 關鍵:許多瀏覽器/代理發送此類型
        'multipart/x-zip',          // 罕見但存在
    ],

    'rar' => [
        'application/x-rar-compressed',
        'application/octet-stream', // 同理
        'application/vnd.rar',      // IANA 標準類型
    ],

    // 同理補充其他常見壓縮格式
    '7z'  => ['application/x-7z-compressed', 'application/octet-stream'],
    'gz'  => ['application/gzip', 'application/x-gzip', 'application/octet-stream'],
    'tar' => ['application/x-tar', 'application/octet-stream'],
];

驗證流程圖解

  1. 用戶選擇文件 → 瀏覽器根據文件擴展名/內容嗅探發送 Content-Type。
  2. CI Upload 類接收 $_FILES['userfile']['type']。
  3. 調用 _file_mime_type() 讀取 mimes.php 對應擴展名允許的類型數組。
  4. 嚴格模式(默認):上傳類型必須完全匹配白名單之一。
  5. 匹配失敗 → 返回錯誤 The filetype you are attempting to upload is not allowed.

進階:雙重驗證(MIME + 魔數)

僅靠 MIME 白名單仍可被偽造。生產環境建議在控制器中增加魔數檢查:

public function do_upload() {
    $config['allowed_types'] = 'zip|rar|7z';
    // ...

    if (!$this->upload->do_upload('package')) {
        $this->session->set_flashdata('error', $this->upload->display_errors());
        redirect('upload');
    }

    $info = $this->upload->data();
    // 二次驗證文件頭
    $signatures = [
        'zip' => [0x50, 0x4B, 0x03, 0x04], // PK..
        'rar' => [0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00], // Rar!...
        '7z'  => [0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C], // 7z¼...
    ];
    $ext = strtolower(pathinfo($info['file_name'], PATHINFO_EXTENSION));
    if (isset($signatures[$ext])) {
        $fp = fopen($info['full_path'], 'rb');
        $header = fread($fp, 8);
        fclose($fp);
        $bytes = array_values(unpack('C*', $header));
        $match = true;
        foreach ($signatures[$ext] as $i => $sig) {
            if (!isset($bytes[$i]) || $bytes[$i] !== $sig) { $match = false; break; }
        }
        if (!$match) {
            @unlink($info['full_path']);
            $this->session->set_flashdata('error', '文件內容與擴展名不符,疑偽造文件');
            redirect('upload');
        }
    }

    // 入庫、業務邏輯...
}

常見誤區

  • ❌ 直接修改 system/libraries/Upload.php → 升級框架覆蓋,違反框架擴展原則。
  • ❌ 設置 $config['allowed_types'] = '*' → 極度危險,繞過所有類型檢查。
  • ✅ 正確做法:僅修改 application/config/mimes.php,屬於應用配置層,不影響框架核心。

CI4 版本差異

CodeIgniter 4 將 MIME 配置移至 app/Config/Mimes.php,結構為關聯數組 'zip' => ['application/zip', ...],修改方式相同。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved