| 經驗交流 |
|
|---|---|
|
關於「檔案上傳」與「WebHD」 | |
問題說明 | |
| PHP 能輕易地處理檔案上傳的問題,也有一堆與目錄/檔案處理相關的函數有供運用。只要規劃得宜,我們可以自行建構一套 WebHD 系統。 | |
我的做法 | |
| 要在使用者端提供上傳介面的話,您需要 File 元件,其使用方法請參閱「表單處理」中之「File」一節之說明。 | |
| 以下就實務上可能遭遇的狀況加以說明: | |
| 一、如何限制使用者上傳的檔案大小 | |
| PHP 預設可接受 2MB 以內的檔案,欲調整這項預設值的話,請在 php.ini 中修改 upload_max_filesize 這項設定值。 | |
| 若使用者上傳一個大小在此一預設值以內的檔案,例如:1 MB。但我們希望單一檔案都不可超過 500 KB 的話,您可以用 $_FILES['UPLOADFILE']['size'] 取得其檔案大小,再用 PHP 的判別式去拒絕他(說明:此處的 UPLOADFILE 請視 Form 中 File 的名稱而定,例如 MyPhoto)。 | |
| 不過,如果使用者傳來一個大小超過系統預設值的檔案,那麼將發生程式無法處理的狀況(錯誤訊息將指稱您的 line 0 有錯誤)。為了解決此一問題,您可以調高 php.ini 中的 upload_max_filesize 設定值,或是在 Form 之中加入 MAX_FILE_SIZE 的參數(請參閱「表單處理」中之「File」一節之說明)。 | |
|
二、為什麼可以接收到上傳的檔名,可是檔案大小卻為 0 | |
| 當 PHP 收到來自使用者的檔案時,會先將它置於一個暫存的目錄下,同時給它一個臨時的檔名(您可以 echo $_FILES['UPLOADFILE']['tmp_name'],查看其目錄與檔名),等待您將它複製到指定的目錄下。 | |
| 如果該暫存目錄已滿,無足夠的空間可供該檔案寫入的話,就會發生「可以接收到上傳的檔名,可是檔案大小卻為 0」之狀況。假如您想改變此暫存目錄之路徑的話,請調整 php.ini 中的 upload_tmp_dir 設定值。 | |
|
三、如何限制使用者上傳的檔案一定是可顯示的圖檔 | |
| 倘若您提供上傳介面,供使用者上傳個人的大頭照,由於瀏覽器只能顯示 GIF、JPEG 與 PNG 三種格式的圖檔,因此我們必須限制上傳的檔案需屬於此類的格式。 | |
| PHP 提供一個圖形處理的函數:GetImageSize,它可用來取得圖形檔案的格式與尺寸。其傳回值是一個陣列,第一個元素是圖片的寬度,單位是像素(pixel);第二個元素是圖片的高度;第三個元素是圖片的檔案格式,其值為 1 代表 GIF 格式,2 為 JPEG/JPG 格式,3 為 PNG 格式,4 為 SWF 格式;第四個元素為圖片的高與寬字串:height=xxx width=yyy。 | |
| 只要上述函數傳回值的第三個元素(索引值 2)為空,即表示該檔不屬於 GIF、JPEG、PNG 或 SWF 之類的格式。例: | |
|
<? $FILE_info = getimagesize($_FILES['UPLOADFILE']['tmp_name']); if ( $FILE_info[2] == "" ) {?> <script language="JavaScript"> alert("您的相片格式不正確,無法在瀏覽器上顯示,請重新選擇!"); history.back(); </script> <? exit; }?> | |
|
四、萬一有兩個使用者上傳了同一檔名的檔案 | |
| 我們可以用 $_FILES['UPLOADFILE']['name'] 取得上傳檔之原始檔名,所以可以用 copy($_FILES['UPLOADFILE']['tmp_name'], "您指定的目錄".$_FILES['UPLOADFILE']['name']),將該檔以原始檔名存入您指定的目錄中。但是若有兩個使用者傳來同檔名的檔案時,會發生新檔覆蓋舊檔的情況。 | |
| 欲解決此一問題,您可以將不同使用者的檔案存放在各自不同的目錄下。或是以您自定的命名規則,重新為檔案命名,使每個檔案的檔名都各不相同;萬一使用者上傳的檔案名稱中含有中文或空白字元,這個方法也可同時改善某些瀏覽器無法正常讀取的情況。 | |
|
五、有人上傳了 PHP 檔,有沒有安全性的問題 | |
| 使用者透過瀏覽器上傳的檔案,其 owner 是 nobody。假如有人上傳了一個 PHP 程式檔,那麼他就可以透過該程式異動 nobody 有權存取的檔案與目錄了。 | |
| 建議您將使用者上傳的檔案,放在一個不能執行 PHP 程式的伺服器上;欲達到這個目的,您可以使用 PHP 中 FTP 這一類的函數。另外,您也可以在 Apache 中,將提供給使用者存放檔案的目錄,設定為不執行 PHP。 | |
|
六、如何刪除一個目錄或檔案 | |
| 在 nobody 有權存取的條件下,您可以使用 unlink 函數來刪除一個檔案。另外,您可以使用 rmdir 函數來刪除一個目錄,但該目錄內的所有檔案必須先被清空。 | |
|
七、如何搬移一個目錄或檔案 | |
| 由於 PHP 並沒有現成的「搬移目錄/檔案」的函數可用,所以我們改以「複製+刪除」的方法,來取代「搬移」的功能。 | |
| 經驗交流 |
|


問題說明