【一】文件上傳javascript
場景:上傳博客,文章,圖片,人臉掃描等php
【二】配置文件css
(1)配置項 html
fille_uploads 開啓上傳功能on;關閉上傳功能off;前端
post_max_size 系統容許post傳參最大值java
upload_max_filesize 系統容許上傳文件最大值jquery
memory_limit 內存使用限制web
建議尺寸:上傳文件大小 < upload_max_filesize < post_max_size < memory_limit後端
(2)拓展數組
此外,還能夠配置臨時文件的存儲位置。
臨時目錄中的臨時文件有效期默認爲腳本週期,即一次請求結束
【三】表單數據類型
表單數據類型有兩種:
(1)字符串類型(字節流編碼);
(2)文件類型(二進制編碼);
*緣由解析*表單提交時:瀏覽器會默認的認爲,表單內數據都是字符串類型(即便使用file文件域)。經過在form上增長enctype屬性,告知瀏覽器表單內的數據不只有字符串,還有文件。從而進行文件提交
上傳圖片和博客時須要設置上傳內容類型爲爲禁止編碼:multipart/form-data
<form> 標籤的 enctype 屬性規定了在提交表單時要使用哪一種內容類型。在表單須要二進制數據時,好比文件內容,請使用 "multipart/form-data"
【四】提交時服務器處理方式
接受瀏覽器請求時,處理好表單內數據。根據數據類型不一樣(2種),採用不一樣處理方式
①字符串類型/字節流,存儲在$_POST變量裏(內存裏)
②文件型數據/二進制,存儲在上傳臨時目錄中
【五】錯誤類型
每一個上傳的臨時文件都有 5個信息:name原始文件名;type類型;tmp_name臨時地址;error是否有錯及錯誤類型;size大小
<form action="" method="post" enctype="multipart/form-data"> <input type="file" name="file" id="file" /> <input type="submit" name="submit" value="提交" /> </form> <?php echo "<pre>"; var_dump($_FILES); echo "</pre>"; ?>
提交後輸出數組:
array(1) { ["file"]=> array(5) { ["name"]=> string(10) "零食.txt" ["type"]=> string(10) "text/plain" ["tmp_name"]=> string(22) "C:\Windows\phpAD25.tmp" ["error"]=> int(0) ["size"]=> int(443) } }
下面說下錯誤類型:01234567
0:無錯誤;
1:文件過大,大於PHP配置upload_max_filesize
2:文件過大,超過表單元素max_file_size
3:上傳部分文件
4:沒有上傳文件
5:上傳空文件
6:沒有找到臨時上傳文件(權限控制)
7:臨時文件寫入失敗
【六】案例:上傳預覽圖片
<!DOCTYPE html> <html> <head> <title>PHP測試demo</title> <link rel="stylesheet" href="./demo.css"> <style type="text/css"> #preview{ display: block; width: 100px; height: 100px; border:1px solid red; } </style> </head> <body> <form action="index.php" method="post" enctype="multipart/form-data"> <label for="file">文件名:</label> <input type="file" name="file" id="file" /> <img id="preview" src=<?php echo "./upload/".$_FILES["file"]["name"]?> alt="點擊上傳圖片"/> <br /> <input type="submit" name="submit" value="提交" /> </form> <?php
//name原始文件名;type類型;tmp_name臨時地址;error是否有錯及錯誤類型;size大小 if ((($_FILES["file"]["type"] == "image/jpg")|| ($_FILES["file"]["type"] == "image/jpeg") || ($_FILES["file"]["type"] == "image/pjpeg"))){ if ($_FILES["file"]["error"] > 0){ echo "報錯: " . $_FILES["file"]["error"] . "<br />"; }else{ echo "文件名: " . $_FILES["file"]["name"] . "<br />"; echo "類型: " . $_FILES["file"]["type"] . "<br />"; echo "大小: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />"; echo "原先保存位置: " . $_FILES["file"]["tmp_name"]."<br>"; //保存 if (file_exists("./upload/" . $_FILES["file"]["name"])){ echo "注意:該文件". $_FILES["file"]["name"] . "已經存在!!!"; }else{ move_uploaded_file($_FILES["file"]["tmp_name"], "./upload/" . $_FILES["file"]["name"]); echo "提交後保存位置: " . "./upload/裏的" . $_FILES["file"]["name"]; } } }else{ echo "Invalid file文件類型不符"; }//注意路徑,例如../php7/a仍然是保存到php7裏,想要保存到php7下的a文件裏的話須要 路徑爲../php7/a/ ?> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script type="text/javascript"> window.FileToSrc = function (file) { if (window.URL) return window.URL.createObjectURL(file); if (window.windcreateObjectURL) return window.createObjectURL(file); if (window.webkitURL) return window.webkitURL.createObjectURL(file); }; $('#file').on('change', function(){ //獲取文件列表對象 var fileList = $('#file')[0].files; //建立文件流獲取文件地址 var src =FileToSrc(fileList[0]); //設置圖片路徑 $("#preview").attr("src", src); }); </script> </body> </html>
【七】上傳步驟
(1)判斷是否有錯誤碼
$_FILES["file"]["error"]讀取錯誤類型
0爲無錯誤,1234567爲有錯誤
if ($_FILES["file"]["error"] > 0){ echo "報錯: " . $_FILES["file"]["error"] . "<br />"; }else{ ... }
(2)自定義判斷文件大小是否超標
除了php.int中規定的上傳最大值外,一般還須要設定業務規定的上傳大小限制
例如:新浪微博或QQ空間頭像圖片規定限制2M,而上傳時又能夠超過2M
此處的判斷文件大小,用於限制實際業務裏想要規定的實際文件大小
(3)判斷後綴名和mime類型是否符合
黑客能夠在圖片裏植入病毒,在附件裏上傳病毒,會在網頁裏插入病毒或者誘惑性圖片。因此,咱們須要上傳文件後綴和mime類型都要進行判斷才行
mime類型是多用途互聯網郵件擴展類型,設定某種擴展名的文件用一種應用程序來打開的方式類型,當擴展文件名被訪問時,瀏覽器會自動使用指定應用程序來打開。多用於指定一些客戶端自定義的文件名,以及一些媒體文件打開方式。
在判斷後綴和MIME類型的時候,會用到PHP的in_array(判斷的值,範圍數組)函數,該函數須要用到兩個參數
咱們用in_array()來判斷文件的後綴名和mime類型是否在容許的範圍內
(4)生成文件名
文件上傳成功後,通常不會讓它保存原名。
由於有些人在原名裏添加了敏感關鍵詞,會違反國家相關法律
因此採用date()、mt_rand()、unique()生成隨機文件名
(5)判斷是不是上傳文件
(6)移動臨時文件到指定位置
<?PHP header("content-type:text/html;charset=utf-8"); if(!empty($_FILES[up_picture][name])){ //判斷上傳文件是否爲空 if($_FILES['up_picture']['error']>0){ //判斷文件是否能夠上傳到服務器 echo "上傳錯誤"; switch($_FILES['up_picture']['error']){ case 1: echo "上傳文件大小超出配置文件規定值"; break; case 2: echo "上傳文件大小超出表單中約定值"; break; case 3: echo "上傳文件不全"; break; case 4: echo "沒有上傳文件"; break; } }else{ if(!is_dir("./upfile/")){ //判斷指定目錄是否存在 mkdir("./upfile/"); //建立目錄 } $path='./upfile/'.time().strstr($_FILES['up_picture']['name'],'.');//定義文件名稱和存儲位置 if(is_uploaded_file($_FILES['up_picture']['tmp_name'])){ //判斷是否經過HTTP POST上傳的 if(!move_uploaded_file($_FILES['up_picture']['tmp_name'],$path)){ //執行上傳 echo "上傳失敗"; }else{ echo "文件".time().$_FILES['up_picture']['name']."上傳成功,大小爲:".$_FILES['up_picture']['size']; } }else{ echo "上傳文件".$_FILES['up_picture']['name']."不合法!"; } } } ?>
【八】步驟解析
(1)判斷錯誤碼
if ($_FILES['myfile']['error'] > 0) { switch ($_FILES['file']['error']) { case '1': echo "文件過大"; break; case '2': echo "文件超出指定大小"; break; case '3': echo "只上傳了部分文件"; break; case '4': echo "沒有上傳文件"; break; case '5': echo "上傳空文件"; break; case '6': echo "沒有找到臨時上傳文件(權限問題)"; break; case '7': echo "臨時文件寫入失敗"; break; } }else{ echo "無錯誤"; }
(2)判斷文件是否超出大小
實際項目中因爲系統硬件的限制,以及存儲設備的限制,不可能讓用戶無限上傳文件。因此要對用戶上傳的文件大小進行限制,能讓應用平穩運行
將文件大小上限定義爲$MAX_FILE_SIZE,若文件大小大於$MAX_FILE_SIZE則退出上傳並錯誤提示
if ($_FILES['myfile']['error'] > 0) { exit("系統出錯0,1,2,3,4,5,6,7"); }else{ $MAX_FILE_SIZE = 1000; if ($_FILES['myfile']['size'] > $MAX_FILE_SIZE) { exit('文件超出指定大小'); } }
(3)判斷文件的mime類型是否正確
例如要求上傳後綴名爲GIF或jpg的文件,當上傳不符合要求的文件時返回錯誤提示
注意:文件類型限制前端便可限制,後端也行
例如:要求只能上傳圖片
前端限制:選擇文件時只會出現圖片選項
<input type="file" name="myfile" id="file" accept="image/*"/>
後端限制:選擇文件時隨意,上傳時判斷進行限制
$allow = array('jpg','gif');//規定容許的類型 $myImg = explode('.', $_FILES['myfile']['name']);//explode()將字符串打散爲數組 $suffix = array_pop($myImg);//array_pop刪除數組末尾元素 if (!in_array($suffix, $allow)) { exit("文件後綴名不符合"); }else{ echo "開始上傳"; }
或者用數組簡單處理
$allow =array("image/jpg","image/jpeg","image/pjqeg","img/gif"); if (!in_array($_FILES['myfile']['type'], $allow)) { exit(文件格式不正確,請檢查); }else{ echo "開始上傳"; }
(4)生成指定文件路徑和文件名
爲了不文件名重複形成的錯誤,能夠按照必定格式生成隨機文件名
$path = "upload/imgs/"; $name = date('y').date('m').date('d').date('h').date('i').date('s').rand(0,9).'.'.'. $suffic';
//date('y').date('m').date('d').date('h').date('i').date('s')按照日期生成隨機數
//rand()生成指定範圍的隨機數
(5)判斷是否上傳文件
if (is_uploaded_file($_FILES['myfile']['tmp_name'])) { ...
}
(6)移動文件到指定位置
使用move_uploaded_file(filename, destination)將文件移動到指定位置保存
if(is_uploaded_file($_FILES['myfile']['tmp_name'])){ if (move_uploaded_file($_FILES['myfile']['tmp_name'], $path. $name)) { echo "上傳成功"; }else{ echo "上傳失敗"; } }else{ echo "不是上傳文件"; }
【九】多文件上傳
(1)可使用$_FILES來接受文件信息,打印並查看數組
<form action="" method="post" enctype="multipart/form-data"> <input type="file" name="file[]"/><hr> <input type="file" name="file[]"/><hr> <input type="submit" name="submit" value="提交" /> </form> <?php echo "<pre>"; var_dump($_FILES['file']); echo "</pre>"; ?>
(2)多文件時,從打印數據能夠看出文件信息被存到數組裏。這時須要用到循環來讀取單個文件的信息。
$array = $_FILES['file']['name']; $length = count($array); for($i=0;$i<$length;$i++){ echo "文件名爲".$array[$i]."<br>"; echo "原先保存位置: " . $_FILES["file"]["tmp_name"][$i]."<br>"; move_uploaded_file($_FILES["file"]["tmp_name"][$i],"./upload/" . $array[$i]); echo "提交後保存位置: " . "./upload/裏的" . $array[$i]."<br>"; }
注意:臨時文件名後需加[$i]來進行區分辨別
【十】文件上傳進度處理
在PHP的5.4版本以前,須要安裝額外的擴展才能監控到文件上傳進度。
5.4版本以後,引入了session.upload_progress的新特性,只須要在php.int裏開啓配置,便可經過session監控文件上傳進度
php.int裏配置項:
session.upoad_progress.enabled 是否啓用上傳進度報告(默認開啓,1開啓,0關閉)
session.upoad_progress.cleanup 是否在上傳完成後及時刪除進度數據(默認開啓,推薦開啓)
session.upload_progress.prefix[=upload_progress_] 進度數據存儲位置
session.upload_progress.freq[=1%] 更新進度的頻率(已經處理的字節數),也支持百分比表示%
session.upload_progress.min_freq[=1.0] 更新進度的時間間隔(秒數)
開啓配置後,能夠經過session,來記錄一個完整的文件上傳進度
代碼推薦網址:http://www.jb51.net/article/56305.htm
另外,UI使用一些插件上傳文件,就能夠獲取上傳進度,不用這麼麻煩,例如 Webuploader
(拓展)
①MIME (Multipurpose Internet Mail Extensions) 多用途Internet郵件擴展,是描述消息內容類型的因特網標準