$tp = array("image/gif","image/pjpeg","image/jpeg","image/png" );
if( ! in_array($_FILES["pictures"]["type"][$key], $tp)) {
echo "";
}
現象:上傳 MP3 時,有的文件名能觸發彈窗,有的(如 `-The Girl Is Mine Ft Brandy Monica (Remix).mp3`)卻不彈窗,檢測失效。
$_FILES["pictures"]["type"][$key] 這種寫法僅適用於多文件上傳且 input name 為數組形式 (`name="pictures[]"`) 時。
// $_FILES 結構
$_FILES["pictures"] = [
"name" => "test.mp3",
"type" => "audio/mpeg", // 字符串,非數組!
"tmp_name" => "/tmp/phpXXXX",
"error" => 0,
"size" => 12345
];
// 正確訪問:$_FILES["pictures"]["type"]
// $_FILES 結構
$_FILES["pictures"] = [
"name" => ["a.mp3", "b.jpg"],
"type" => ["audio/mpeg", "image/jpeg"], // 數組
"tmp_name" => ["/tmp/php1", "/tmp/php2"],
"error" => [0, 0],
"size" => [123, 456]
];
// 正確訪問:$_FILES["pictures"]["type"][0], $_FILES["pictures"]["type"][1]
瀏覽器根據文件擴展名猜測 MIME 類型填入 `type` 字段:
關鍵點:代碼中 `$key` 變量來源不明。若單文件上傳但代碼按多文件寫法 `$_FILES["pictures"]["type"][$key]`,當 `$key=0` 時:
這解釋了「有的彈窗有的不彈窗」的隨機性:取決於 `$key` 值和 `type` 字符串首字符是否碰巧匹配數組值。
$allowedTypes = ["image/gif", "image/jpeg", "image/png", "image/pjpeg"]; // 建議統一小寫
// 兼容單文件/多文件寫法
$files = $_FILES["pictures"];
$isMultiple = is_array($files["name"]);
$indices = $isMultiple ? array_keys($files["name"]) : [null];
foreach ($indices as $key) {
$type = $isMultiple ? $files["type"][$key] : $files["type"];
$name = $isMultiple ? $files["name"][$key] : $files["name"];
$error = $isMultiple ? $files["error"][$key] : $files["error"];
if ($error !== UPLOAD_ERR_OK) continue; // 跳過錯誤文件
// 核心修正:嚴格類型比較,轉小寫
if (!in_array(strtolower($type), $allowedTypes, true)) {
// 記錄日誌、返回錯誤、拒絕上傳
log_upload_rejection($name, $type, "類型不在白名單");
continue;
}
// 進一步驗證:文件內容檢測 (finfo)
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$realType = finfo_file($finfo, $files["tmp_name"][$key] ?? $files["tmp_name"]);
finfo_close($finfo);
if (!in_array($realType, $allowedTypes, true)) {
log_upload_rejection($name, $realType, "內容類型偽裝");
continue;
}
// 移動文件...
}