上传问题总结(文件大小检测,大文件上传)
PHP上傳問題總結(文件大小檢測,大文件上傳)
????? 由于涉及到本地和服務器兩方面的安全問題,所以基于input type="file"形式的頁面文件上傳一直處于一個很尷尬的位置。一方面,用戶不希望隱私泄露,所以瀏覽器無法對用戶在上傳時選擇的文件做有效的判 斷。另一方面,為了服務器端的安全,減輕傳輸負擔,系統又希望能在用戶開始上傳之前就將非法的文件拒之門外。
?????? 一來一去,基于原始input方式的上傳,成為網絡存儲網站避之唯恐不及的遺留性問題,也造就了現在千奇百怪的插件、上傳客戶端。
?????? input方式的上傳就如此之差么?當然不是。上傳文件不大的時候,它還是非常簡單可靠的,在PHP中,我們只需要一個復合型表單
[xml]?view plaincopy????? 一個輸入框
[xml]?view plaincopy?????? 和服務器端的一行代碼
[php]?view plaincopy?????? 就可以實現整個上傳過程。
?????? 但隨文件增大,表單上傳的不足就會暴露出來。尤其是我們想取得最基本的文件大小來阻止過大文件上傳這一簡單的想法,也變得如此困難。以下一一道來:
通過MAX_FILE_SIZE
??????? 我們經常會在手冊里讀到:
MAX_FILE_SIZE 隱藏字段(單位為字節)必須放在文件輸入字段之前,其值為接收文件的最大尺寸。這是對瀏覽器的一個建議,PHP 也會檢查此項。在瀏覽器端可以簡單繞過此設置,因此不要指望用此特性來阻擋大文件。實際上,PHP 設置中的上傳文件最大值是不會失效的。但是最好還是在表單中加上此項目,因為它可以避免用戶在花時間等待上傳大文件之后才發現文件過大上傳失敗的麻煩。
?????? 顯然PHP的開發者們也考慮到了大文件上傳的問題,但就像手冊所說,MAX_FILE_SIZE只是對瀏覽器的一個建議,事實上目前為止所有主流的瀏覽器并沒有采納這個建議,所以采用MAX_FILE_SIZE約束文件大小形同擺設,不可行。
通過服務器端
?????? MAX_FILE_SIZE既然無效,那么用戶可以將文件上傳到服務器,服務器端通過$_FILES['userfile']['size']判斷用戶上 傳的文件大小,然后決定是否接受上傳并返回信息。暫且排除服務器的負荷以及可能存在的惡意破壞行為,這種解決方案聽起來無非是浪費一部分帶寬,也能對用戶 上傳文件作出約束。
?????? 但這也是不可行的,PHP的文件上傳受到php.ini以下這些設置的影響:
- post_max_size
- upload_max_filesize
- max_execution_time
- memory_limit
?????? 雖然設置方法在手冊?中都有比較詳細的說明,之所以仍然說此方法不可行,是因為php執行腳本在超過memory_limit時,該次的POST數據會全部丟失并且不會報錯!
?????? 試想用戶填寫了一個超長的表單,并伴隨一個超過memory_limit的文件一起上傳,經過了漫長的等待時間之后發現等來的又是一張干干凈凈的空白表 單,那是何等印象深刻的用戶體驗啊。更何況數十M的服務器流量僅僅用來檢測文件大小,是現在的網絡環境不允許的。
通過Javascript
??????? Javascript是基于瀏覽器的,雖然JS能完成很多看似不可能的任務,但瀏覽器做不到的事情JS同樣無法做到。先天不足注定了這項工作僅僅靠Javascript是無法勝任的。不過一些IE Only的方法?也還是存在的,僅作參考?。
通過Flash
???????? Flash的FileReference類提供了一套比較全面的文件處理方法,現在大多數大文件上傳也都采用了基于Flash的方案。如果利用Flash與Js交互,能否實現客戶端對文件大小的檢測呢?答案是可行的。
?????? 首先在flash文件中實例化FileReference類。
[jscript]?view plaincopy?????? 基于這個類就可以用Flash提供的file browse和SelectFile事件替代瀏覽器的事件。我們需要:
?????? 1.綁定SelectFile
[jscript]?view plaincopy?????? 2.創建一個供Js訪問的對象,用來放置flash得到的文件信息
[jscript]?view plaincopy?????? 3.創建file browse方法
[jscript]?view plaincopy?????? 4.當SelectFile事件觸發的時候,傳遞文件信息
[jscript]?view plaincopy?????? 5.將browseFile方法公開可供Js調用
[jscript]?view plaincopy?????? 6.將得到的文件信息傳遞給Js
[jscript]?view plaincopy?????? 現在我們已經可以通過Js獲得由flash傳遞來的文件大小信息了,具體的實現可以參看Demo?。
結論
?????? 問題至此似乎已經得到解決了,我們已經成功的校驗了文件大小不是么。但本文的最終結論是,基于Flash的文件大小校驗,仍然不可行。
?????? 文件大小校驗的唯一目的,是為了上傳。在上面的Demo中可以看到校驗成功的文件名會顯示在一個輸入框里。熟悉上傳的同學不覺得少了什么嗎?沒錯,通過 flash只能得到文件名,而無法得到文件的完整路徑,而文件路徑卻是input方式上傳的必要條件。所以雖然可以成功的通過Flash與Js交互校驗文 件大小,但我們能做到的也僅僅只是校驗而已,之后想要上傳,唯有繼續通過flash方式進行。
?????? Flash開發出于安全考慮屏蔽了文件的完整路徑這無可厚非,不過文件上傳,尤其是PHP環境下的文件校驗上傳方案仍然沒有得到最好的解決。
?????? 當然彌補的方法有很多:
- 基于Perl的項目?FileChucker?,?XUpload?,?Uber-Uploader
- 基于Flash的項目?SWFUpload
- 還有筒子用PHP直接在服務器華麗的建立socket鏈接?。
????? 但終究我希望有一天能看到僅基于HTML就能實現的嚴整健壯的上傳方案,但愿這一天不會太遠。
????? 最后是本次的代碼下載?。
?
?
php文件上傳大小設置詳解
用php上傳文件,問題最多的就是上傳大體積文件時出現錯誤。?
這就涉及到php的配置文件:php.ini?
在此配置文件中,有這么幾個值是跟文件上傳有密切關系的:?
file_uploads = on //是否允許系統支持文件上傳?
;upload_tmp_dir //臨時文件的存儲路徑,linux下為系統默認路徑,win32下需要指定?
upload_max_filesize = 2m //允許文件上傳最大體積?
post_max_size = 2m //通過post方法給php時,php所能接受的最大數據容量?
如果你上傳的文件體積在8m一下(通常情況),那修改以上設置就可以滿足你的要求了。。?
但要>8m,那除了上面幾個值,還要特別關注另外兩個值了:?
max_execution_time = 30 //每個script所執行的最大時間(php上傳就時,體積大了,就是個時間問題)?
memory_limit = 8m //每個script所能消耗的最大memory?
試著把這兩個值改大些。一般就可以解決大多數問題了。?
就此推斷,上傳文件的體積是可以無窮大的。但還要考慮你的網絡情況,等等。?
在php.net上,有人說按照這個方法改了后,大于100m的文件還是會出錯。?
不知道是不是php本身的問題了:
?
?
php實現文件上傳的一些經驗
-
//圖片上傳處理
$upload_file=$_FILES['upload_file']['tmp_name'];
echo $upload_file;
$upload_file_name=$_FILES['upload_file']['name'];
$type=strstr($upload_file_name, '.');
if($upload_file=="")
{
$newname="0.jpg";?
}
else
{
$newname=$newid.$type;
}
//$newname=$newid.$type;$intonew2="update mms_news_info set col_image='$newname' where col_id='$newid'";
mysql_query($intonew2,$db);?
if($upload_file){
$file_size_max = 1000*1000;// 1M限制文件上傳最大容量(bytes)
$store_dir = "neirongimg/";// 上傳文件的儲存位置
$accept_overwrite = 1;//是否允許覆蓋相同文件
// 檢查文件大小
if ($upload_file_size > $file_size_max) {
echo "對不起,你的文件容量大于規定";
exit;
}// 檢查讀寫文件
if (file_exists($store_dir . $upload_file_name) && $accept_overwrite) {
Echo?? "存在相同文件名的文件";
exit;
}//復制文件到指定目錄
if (!move_uploaded_file($upload_file,$store_dir.$newname)) {
echo "復制文件失敗";
exit;
}}
Echo?? "<p>你上傳了文件:";
echo? $_FILES['upload_file']['name'];
echo "<br>";
//客戶端機器文件的原名稱。Echo?? "文件的 MIME 類型為:";
echo $_FILES['upload_file']['type'];
//文件的 MIME 類型,需要瀏覽器提供該信息的支持,例如“image/gif”。?
echo "<br>";Echo?? "上傳文件大小:";
echo $_FILES['upload_file']['size'];
//已上傳文件的大小,單位為字節。?
echo "<br>";Echo?? "文件上傳后被臨時儲存為:";
echo $_FILES['upload_file']['tmp_name'];
//文件被上傳后在服務端儲存的臨時文件名。?
echo "<br>";
$Erroe=$_FILES['upload_file']['error'];
switch($Erroe){
case 0:
Echo?? "上傳成功"; break;
case 1:
Echo?? "上傳的文件超過了 php.ini 中 upload_max_filesize 選項限制的值."; break;
case 2:
Echo?? "上傳文件的大小超過了 HTML 表單中 MAX_FILE_SIZE 選項指定的值。";??? break;
case 3:
Echo?? "文件只有部分被上傳";break;
case 4:
Echo?? "沒有文件被上傳";break;
}??//圖片上傳處理
?>
+++++++++++++++++++++++++++++++++
關于錯誤信息的解釋
從 PHP 4.2.0 開始,PHP 將隨文件信息數組一起返回一個對應的錯誤代碼。該代碼可以在文件上傳時生成的文件數組中的 ['error'] 字段中被找到,也就是 $_FILES['userfile']['error']。?
UPLOAD_ERR_OK
值:0; 沒有錯誤發生,文件上傳成功。UPLOAD_ERR_INI_SIZE
值:1; 上傳的文件超過了 php.ini 中 upload_max_filesize 選項限制的值。UPLOAD_ERR_FORM_SIZE
值:2; 上傳文件的大小超過了 HTML 表單中 MAX_FILE_SIZE 選項指定的值。UPLOAD_ERR_PARTIAL
值:3; 文件只有部分被上傳。UPLOAD_ERR_NO_FILE
值:4; 沒有文件被上傳。
注: 這些在 PHP 4.3.0 之后變成了 PHP 常量。
PHP 能夠接受任何來自符合 RFC-1867 標準的瀏覽器(包括 Netscape Navigator 3 及更高版本,Microsoft Internet Explorer 3 加微軟補丁,或者更高版本)上傳的文件。PHP 的這種特性使得我們既可以上傳文本文件,也可以上傳二進制文件。利用 PHP 的認證和文件操作函數,您就可以控制誰有上傳的權限,以及在文件上傳后進行哪些處理。相關的設置: 請參閱 php.ini 的 file_uploads、 upload_max_filesize、upload_tmp_dir 以及 post_max_size 設置選項。
請注意 PHP 也支持 PUT 方法的文件上傳,Netscape Composer 和 W3C 的 Amaya 客戶端使用這種方法。請參閱 PUT 方法支持以獲取更多信息。
您可以如下建立一個特殊的表單來支持文件上傳:
例子 18-1. 文件上傳表單
<form enctype="multipart/form-data" action="_URL_" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="30000">
Send this file: <input name="userfile" type="file">
<input type="submit" value="Send File">
</form>
以上范例中的“_URL_”應該替換成指向一個 PHP 文件的真實 URL。MAX_FILE_SIZE 隱藏域(單位為字節)必須先于文件輸入域,其值為接收文件的最大尺寸。同時,要保證您的文件上傳表單中要有 enctype="multipart/form-data",否則文件上傳將不能工作。
警告?
MAX_FILE_SIZE 的值只是對瀏覽器的一個建議,實際上它可以被簡單的繞過。因此不要把對瀏覽器的限制寄希望于該值。實際上,PHP 設置中的上傳文件最大值,是不會失效的。但是最好還是在表單中加上 MAX_FILE_SIZE,因為它可以避免用戶在花時間等待上傳大文件之后才發現該文件太大了的麻煩。
為上傳文件定義的變量會根據 PHP 的版本及設置的不同而不同。自動全局變量 $_FILES 從 PHP 4.1.0 版本開始被支持。在這之前,從 4.0.0 版本開始,PHP 支持 $HTTP_POST_FILES 數組。這些數組將包含所有關于您上傳的文件的信息,其中,我們推薦您使用 $_FILES。如果 PHP 的設置選項 register_globals 為 on,則相關的變量名將也會存在。從 PHP 4.2.0 版本開始,register_globals 的默認值被設為 off。以上范例中 $_FILES 數組的內容如下所示。我們假設文件上傳字段的名稱如上例所示,為 userfile。名稱可隨意命名。
$_FILES['userfile']['name']
客戶端機器文件的原名稱。$_FILES['userfile']['type']
文件的 MIME 類型,需要瀏覽器提供該信息的支持,例如“image/gif”。$_FILES['userfile']['size']
已上傳文件的大小,單位為字節。$_FILES['userfile']['tmp_name']
文件被上傳后在服務端儲存的臨時文件名。$_FILES['userfile']['error']
和該文件上傳相關的錯誤代碼。['error'] 是在 PHP 4.2.0 版本中增加的。
注: 在 PHP 4.1.0 版本以前該數組的名稱為 $HTTP_POST_FILES,它并不像 $_FILES 一樣是自動全局變量。PHP 3 不支持 $HTTP_POST_FILES 數組。當 php.ini 中的 register_globals 被設置為 on 時,您可以使用更多的變量。例如,$userfile_name 等價于 $_FILES['userfile']['name'],$userfile_type 等價于 $_FILES['userfile']['type'] 等。請記住從 PHP 4.2.0 開始,register_globals 的默認值為 off,因此我們建議您不要依賴于改設置項而使用剛剛提到的那些附加變量。
文件被上傳后,默認地會被儲存到服務端的默認臨時目 錄中,除非您將 php.ini 中的 upload_tmp_dir 設置為了其它的路徑。服務端的默認臨時目錄可以通過更改 PHP 運行環境的環境變量 TMPDIR 來重新設置,但是在 PHP 腳本內部通過運行 putenv() 函數來設置是不起作用的。該環境變量也可以用來確認其它的操作也是在上傳的文件上進行的。 例子 18-2. 使文件上傳生效
請查閱函數 is_uploaded_file() 和 move_uploaded_file() 以獲取進一步的信息。以下范例處理由表單提供的文件上傳。
<?php
// 在 4.1.0 以前的 PHP 中,需要用 $HTTP_POST_FILES 代替 $_FILES。
// 在 4.0.3 以前的 PHP 中,需要用 copy() 和 is_uploaded_file() 來代替 move_uploaded_file()。$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir. $_FILES['userfile']['name'];
print "<pre>";
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploaddir . $_FILES['userfile']['name'])) {
print "File is valid, and was successfully uploaded.? Here's some more debugging info:/n";
print_r($_FILES);
} else {
print "Possible file upload attack!? Here's some debugging info:/n";
print_r($_FILES);
}
print "</pre>";
?>
接受上傳文件的 PHP 腳本必須在文件上傳后進行判斷,來決定接下來要對該文件進行那些操作。例如,您可以通過 $_FILES['userfile']['size'] 變量來忽略尺寸太大或太小的文件,也可以通過
轉自:http://hi.baidu.com/%BA%EE%BB%E1%C1%C1boke/blog/item/b92909a01c0e918147106431.html
來源:http://blog.csdn.net/johe931012/article/details/39780001
總結
以上是生活随笔為你收集整理的上传问题总结(文件大小检测,大文件上传)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2.最合适汽车使用的燃料电池是燃料电池?
- 下一篇: 深入php-fpm的两种进程管理模式详解