本特性可以使用戶(hù)上傳文本和二進(jìn)制文件。用 PHP 的認證和文件操作函數,可以完全控制允許哪些人上傳以及文件上傳后怎樣處理。
PHP 能夠接受任何來(lái)自符合 RFC-1867 標準的瀏覽器上傳的文件。
注意: 相關(guān)的設置
請參閱 php.ini 的 file_uploads,upload_max_filesize,upload_tmp_dir,post_max_size 以及 max_input_time 設置選項。
請注意 PHP 也支持 PUT 方法的文件上傳,Netscape Composer 和 W3C 的 Amaya 客戶(hù)端使用這種方法。請參閱對 PUT 方法的支持以獲取更多信息。
示例 #1 文件上傳表單
可以如下建立一個(gè)特殊的表單來(lái)支持文件上傳:
<!-- 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__
應該被換掉,指向一個(gè)真實(shí)的 PHP 文件。
MAX_FILE_SIZE
隱藏字段(單位為字節)必須放在文件輸入字段之前,其值為接收文件的最大尺寸。這是對瀏覽器的一個(gè)建議,PHP
也會(huì )檢查此項。在瀏覽器端可以簡(jiǎn)單繞過(guò)此設置,因此不要指望用此特性來(lái)阻擋大文件。實(shí)際上,PHP
設置中的上傳文件最大值是不會(huì )失效的。但是最好還是在表單中加上此項目,因為它可以避免用戶(hù)在花時(shí)間等待上傳大文件之后才發(fā)現文件過(guò)大上傳失敗的麻煩。
注意:
要確保文件上傳表單的屬性是
enctype="multipart/form-data"
,否則文件上傳不了。
全局變量 $_FILES 包含有所有上傳的文件信息。 數組的內容來(lái)自以下范例表單。我們假設文件上傳字段的名稱(chēng)如下例所示,為 userfile。名稱(chēng)可隨意命名。
客戶(hù)端機器文件的原名稱(chēng)。
文件的 MIME 類(lèi)型,如果瀏覽器提供此信息的話(huà)。一個(gè)例子是“image/gif
”。不過(guò)此
MIME 類(lèi)型在 PHP 端并不檢查,因此不要想當然認為有這個(gè)值。
已上傳文件的大小,單位為字節。
文件被上傳后在服務(wù)端儲存的臨時(shí)文件名。
和該文件上傳相關(guān)的錯誤代碼。
文件被上傳后,默認地會(huì )被儲存到服務(wù)端的默認臨時(shí)目錄中,除非 php.ini 中的 upload_tmp_dir 設置為其它的路徑。服務(wù)端的默認臨時(shí)目錄可以通過(guò)更改 PHP 運行環(huán)境的環(huán)境變量 TMPDIR 來(lái)重新設置,但是在 PHP 腳本內部通過(guò)運行 putenv() 函數來(lái)設置是不起作用的。該環(huán)境變量也可以用來(lái)確認其它的操作也是在上傳的文件上進(jìn)行的。
示例 #2 驗證上傳的文件
請查閱函數 is_uploaded_file() 和 move_uploaded_file() 以獲取進(jìn)一步的信息。 以下范例處理由表單提供的文件上傳。
<?php
$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
echo '<pre>';
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 "</pre>";
?>
接受上傳文件的 PHP 腳本為了決定接下來(lái)要對該文件進(jìn)行哪些操作,應該實(shí)現任何邏輯上必要的檢查。例如可以用 $_FILES['userfile']['size'] 變量來(lái)排除過(guò)大或過(guò)小的文件,也可以通過(guò) $_FILES['userfile']['type'] 變量來(lái)排除文件類(lèi)型和某種標準不相符合的文件,但只把這個(gè)當作一系列檢查中的第一步,因為此值完全由客戶(hù)端控制而在 PHP 端并不檢查。同時(shí),還可以通過(guò) $_FILES['userfile']['error'] 變量來(lái)根據不同的錯誤代碼來(lái)計劃下一步如何處理。不管怎樣,要么將該文件從臨時(shí)目錄中刪除,要么將其移動(dòng)到其它的地方。
如果表單中沒(méi)有選擇上傳的文件,則 PHP 變量 $_FILES['userfile']['size'] 的值將為 0,$_FILES['userfile']['tmp_name'] 將為空。
如果該文件沒(méi)有被移動(dòng)到其它地方也沒(méi)有被改名,則該文件將在表單請求結束時(shí)被刪除。
示例 #3 上傳一組文件
PHP 的 HTML 數組特性甚至支持文件類(lèi)型。
<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];
// basename() may prevent filesystem traversal attacks;
// further validation/sanitation of the filename may be appropriate
$name = basename($_FILES["pictures"]["name"][$key]);
move_uploaded_file($tmp_name, "data/$name");
}
}
?>
File upload progress bar can be implemented using Session Upload Progress.