<form action="?" method="post" enctype="multipart/form-data">
檔案上傳:<input type="file" name="file" id="file"/>
<input type="submit" id="send" value="提交"/>
</form>
<script>
document.getElementById("send").onclick = function() {
var file = document.getElementById("file").value;
if (file.length < 1) {
alert('請選擇圖片');
return false;
}
// 進階:限制副檔名
var ext = file.match(/\.([^.]+)$/)[1].toLowerCase();
if (['jpg','png','gif','pdf'].indexOf(ext) === -1) {
alert('檔案類型不支援');
return false;
}
};
</script>
<?php
// 必須檢查 tmp_name,單檢 name 或 size 不可靠
if (!empty($_FILES['file']['tmp_name'])) {
echo '已選擇檔案';
} else {
echo '請選擇檔案';
}
?>
僅檢查副檔名或 MIME 不安全,需讀取檔案前 2 位元組特徵碼:
<?php
function file_type($filename) {
$file = fopen($filename, "rb");
$bin = fread($file, 2); // 讀取前 2 位元組
fclose($file);
$strInfo = @unpack("C2chars", $bin);
$typeCode = intval($strInfo['chars1'] . $strInfo['chars2']);
$fileType = '';
switch ($typeCode) {
case 7790: $fileType = 'exe'; break;
case 7784: $fileType = 'midi'; break;
case 8297: $fileType = 'rar'; break;
case 8075: $fileType = 'zip'; break;
case 255216: $fileType = 'jpg'; break;
case 7173: $fileType = 'gif'; break;
case 6677: $fileType = 'bmp'; break;
case 13780: $fileType = 'png'; break;
default: $fileType = 'unknown: ' . $typeCode;
}
// 修正特殊情況(有號整數解讀問題)
if ($strInfo['chars1'] == '-1' && $strInfo['chars2'] == '-40') return 'jpg';
if ($strInfo['chars1'] == '-119' && $strInfo['chars2'] == '80') return 'png';
return $fileType;
}
echo file_type('start.php'); // 輸出類型代碼
?>
| 格式 | Hex | Decimal (前2字節) |
|---|---|---|
| JPG | FF D8 | 255 216 |
| PNG | 89 50 | 137 80 |
| GIF | 47 49 | 71 73 |
| BMP | 42 4D | 66 77 |
| ZIP | 50 4B | 80 75 |
| RAR | 52 61 | 82 97 |
tmp_name 存在且讀取檔頭確認類型upload_max_filesize, post_max_size)