最近用PHP做了一個簡單的上傳功能,結果出現了一個意想不到的問題。我上傳的檔案,在擷取$_FILES的時候發現檔案名稱的第一個字元被截掉了,因為最開始上傳的一直是數字或者字母為名稱的文檔,也沒有太在意這個問題,等到上傳中文名稱的文檔的時候,問題來了,因為只截取了一個字元,而一個漢字是兩個字元,所以,亂碼出現了。而且不管是本機還是伺服器,都出現同樣的問題。到這時,我就不得不開始尋找原因了。
代碼如下,一目瞭然。
檔案upload.php的內容為:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head> <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"> <title>上傳檔案</title></head><body><div id="welcome"> <form method="post" action="upload2.php" enctype="multipart/form-data" > <input name="content" type="file"></input> <input type="submit"/> </form></div></body></html>
submit之後post到頁面upload2.php,我們再看看裡面的內容:
<?php var_export($_FILES);
邏輯很簡單毫無懸念對不對?但是就是出現了我上面描述的那個蛋疼的錯誤,具體的情況是什麼樣子的呢?我來描述一下。
首先我選中一個名稱為“mima.txt”的檔案,確定之後,列印出來的結果為:
array ( 'content' => array ( 'name' => 'ima.txt', 'type' => 'text/plain', 'tmp_name' => 'D:\\wamp\\tmp\\php322.tmp', 'error' => 0, 'size' => 379, ), )
大家可以看到,第一個字元被截掉了,“mima.txt”變成了"ima.txt"。
現在我們來看看中文的, 我選中一個名稱為“建立文字文件.txt”的檔案,然後上傳,列印出來的結果為:
array ( 'content' => array ( 'name' => '��建 文字文件.txt', 'type' => 'text/plain', 'tmp_name' => 'D:\\wamp\\tmp\\php327.tmp', 'error' => 0, 'size' => 10, ), )
很好,亂碼了。
通過我各種孜孜不倦的求助搜尋引擎,求助好友以及自救之後,一個網頁讓我豁然開朗。
https://bugs.php.net/bug.php?id=55510
為大家節選一部分
I started going back version by version from 5.3.8 to see where the problem started, and it seems to have begun with 5.3.7, as 5.3.6 works correctly. Once again, I'm just replacing PHP builds -- I'm not modifying any else. With 5.3.6, I get back what I would expect:array(1) { ["filename"]=> array(5) { ["name"]=> string(10) "readme.txt" ["type"]=> string(10) "text/plain" ["tmp_name"]=> string(31) "C:\temp\file_upload\php594F.tmp" ["error"]=> int(0) ["size"]=> int(22) } } With 5.3.7 and 5.3.8, I get back the missing first letter:array(1) { ["filename"]=> array(5) { ["name"]=> string(10) "eadme.txt" ["type"]=> string(10) "text/plain" ["tmp_name"]=> string(31) "C:\temp\file_upload\php594F.tmp" ["error"]=> int(0) ["size"]=> int(22) } } With 5.4.beta1-dev, I'm back to getting everything that I expect:array(1) { ["filename"]=> array(5) { ["name"]=> string(10) "readme.txt" ["type"]=> string(10) "text/plain" ["tmp_name"]=> string(31) "C:\temp\file_upload\php594F.tmp" ["error"]=> int(0) ["size"]=> int(22) } }
也就是說是PHP5.3.8存在這個問題,而我檢查之後發現,我本機及伺服器的PHP版本都是5.8.3,雙雙躺槍。
兩種簡單的解決方案:
一.升級你的PHP版本吧。或者後退也行啊。不要用5.3.8了。
二.重新命名檔案之後再上傳吧,我直接用的隨機數加目前時間戳再加上檔案拓展名。直接繞過檔案名稱被截斷的問題。當然,如果需要儲存原檔案名稱又不想修改你的PHP環境的話,那你可以放一個hidden儲存你的檔案名稱,提交過去或者hidden裡面的檔案名稱即可。