本特性可以使用戶上傳文字和二進位。用 PHP 的認證和檔案操作函數,可以完全控制允許哪些人上傳以及檔案上傳後如何處理。
PHP 能夠接受任何來自符合 RFC-1867 標準的瀏覽器(包括 Netscape Navigator 3 及更高版本,打了補丁的 Microsoft Internet Explorer 3 或更高版本)上傳的檔案。
Note: 相關的設定
請參考 php.ini 的 file_uploads,upload_max_filesize,upload_tmp_dirpost_max_size 及 max_input_time 設定選項。
Example #1 檔案上傳表單
可以如下建立一個特殊的表單來支援檔案上傳:
<!-- The data encoding type, enctype, MUST be specified as below --> <form enctype="multipart/form-data" action="__URL__" method="POST"> <!-- MAX_FILE_SIZE must precede the file input field --> <input type="hidden" name="MAX_FILE_SIZE" value="30000" /> <!-- Name of input element determines name in $_FILES array --> Send this file: <input name="userfile" type="file" /> <input type="submit" value="Send File" /> </form>
以上範例中的 __URL__ 應該被換掉,指向一個真實的 PHP 檔案。
MAX_FILE_SIZE 隱藏欄位(單位為位元組)必須放在檔案輸入欄位之前,其值為接收檔案的最大尺寸。這是對瀏覽器的建議,PHP 也會檢查此項目。在瀏覽器端可以簡單繞過此設置,因此不要指望用此特性來阻擋大型檔案。實際上,PHP 設定中的上傳檔案最大值是不會失效的。但最好還是在表單中加上此項目,因為它可以避免用戶在花時間等待上傳大檔案之後才發現檔案過大上傳失敗的麻煩。
注意:
要確保檔案上傳表單的屬性是 enctype="multipart/form-data",否則檔案上傳不了。
全域變數 $_FILES 自 PHP 4.1.0 起存在(在更早的版本中以 $HTTP_POST_FILES 取代)。此數組包含有所有上傳的檔案資訊。
以上範例中 $_FILES 陣列的內容如下圖所示。我們假設檔案上傳欄位的名稱如上例所示,為 userfile。名稱可隨意命名。
$_FILES['userfile']['name']
客戶端機器檔案的原名稱。
$_FILES['userfile']['type']
文件的 MIME 類型,如果瀏覽器提供此資訊的話。一個例子是“image/gif”。不過此 MIME 類型在 PHP 端並不檢查,因此不要想當然認為有這個值。
$_FILES['userfile']['size']
已上傳檔案的大小,單位為位元組。
$_FILES['userfile']['tmp_name']
檔案上傳後在服務端儲存的暫存檔案名稱。
$_FILES['userfile']['error']
和該檔案上傳相關的錯誤代碼。此項目是在 PHP 4.2.0 版本中增加的。
檔案被上傳後,預設會儲存到服務端的預設暫存目錄中,除非 php.ini 中的 upload_tmp_dir 設定為其它的路徑。服務端的預設臨時目錄可以透過更改 PHP 運行環境的環境變數 TMPDIR 來重新設置,但是在 PHP 腳本內部透過執行 putenv() 函數來設定是不起作用的。這個環境變數也可以用來確認其它的操作也是在上傳的檔案上進行的。
Example #2 讓檔案上傳生效
請參考函數 is_uploaded_file() 和 move_uploaded_file() 以取得進一步的資訊。以下範例處理由表單提供的檔案上傳。
<?php // 在PHP4.1.0版本以前, 应该使用$HTTP_POST_FILES来替代$_FILES. $uploaddir = '/var/www/uploads/'; $uploadfile = $uploaddir . basename($_FILES['userfile']['name']); echo '<pre class="brush:php;toolbar:false">'; if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) { echo "File is valid, and was successfully uploaded.\n"; } else { echo "Possible file upload attack!\n"; } echo 'Here is some more debugging info:'; print_r($_FILES); print ""; ?>
接受上傳檔案的 PHP 腳本為了決定接下來要對該檔案進行哪些操作,應該實作任何邏輯上必要的檢查。例如可以用 $_FILES['userfile']['size'] 變數來排除過大或過小的文件,也可以透過 $_FILES['userfile']['type'] 變數來排除檔案類型和某種標準不相符合的文件,但只把這個當作一系列檢查中的第一步,因為此值完全由客戶端控製而在PHP 端並不檢查。自 PHP 4.2.0 起,也可以透過 $_FILES['userfile']['error'] 變數來根據不同的錯誤代碼來規劃下一步如何處理。不管怎樣,要么將該文件從臨時目錄中刪除,要么將其移動到其它的地方。
如果表單中沒有選擇上傳的文件,則 PHP 變數 $_FILES['userfile']['size'] 的值將為 0,$_FILES['userfile']['tmp_name'] 將為空白。
如果該檔案沒有被移動到其它地方也沒有被改名,則該檔案將在表單請求結束時被刪除。
Example #3 上傳一組檔案
PHP 的 HTML 陣列特性甚至支援檔案類型。
<form action="" method="post" enctype="multipart/form-data"> <p>Pictures: <input type="file" name="pictures[]" /> <input type="file" name="pictures[]" /> <input type="file" name="pictures[]" /> <input type="submit" value="Send" /> </p> </form>
<?php foreach ($_FILES["pictures"]["error"] as $key => $error) { if ($error == UPLOAD_ERR_OK) { $tmp_name = $_FILES["pictures"]["tmp_name"][$key]; $name = $_FILES["pictures"]["name"][$key]; move_uploaded_file($tmp_name, "data/$name"); } } ?>