7.PHP表單傳值

思考:Web2.0的顯著特點信息共建,也就是用戶可以將自己想要分享的數(shù)據(jù)提交給服務器端。但是用戶能夠看到的是最終的HTML呈現(xiàn)出來的效果,那么用戶如何實現(xiàn)數(shù)據(jù)的提交呢?

引入:用戶是在體驗終端瀏覽器端,那邊能夠被瀏覽器解析的只有HTML、CSS和JavaScript,而CSS是一種樣式語言,是用來美化布局效果的,JavaScript也是一種動態(tài)效果語言,不能直接實現(xiàn)數(shù)據(jù)的交互。因此只有HTML本身可以實現(xiàn)數(shù)據(jù)的提交操作。而HTML中標簽眾多,也并非所有標簽都能夠進行數(shù)據(jù)提交,只有表單標簽可以實現(xiàn)。

表單傳值意義【掌握】

定義:表單傳值,就是通過在HTML中使用表單標簽,通過表單來獲取用戶的數(shù)據(jù),然后通過HTTP協(xié)議將數(shù)據(jù)提交給后臺。

1.表單傳值的意義:表單傳值能夠幫助網(wǎng)站收集用戶數(shù)據(jù),實現(xiàn)用戶與網(wǎng)站后臺的數(shù)據(jù)交互。
2.表單傳值方式:表單傳值就是利用HTML的一組特點標簽,然后通過瀏覽器解析后,給用戶提供一種數(shù)據(jù)錄入的入口,并且允許用戶在數(shù)據(jù)錄入后,實現(xiàn)數(shù)據(jù)提交。

總結:表單傳值是能夠?qū)崿F(xiàn)動態(tài)網(wǎng)站的非常重要的一步,不僅能夠?qū)崿F(xiàn)用戶的數(shù)據(jù)提交,還能幫助用戶實現(xiàn)動態(tài)的數(shù)據(jù)定制。


思考:表單傳值能夠幫助用戶實現(xiàn)數(shù)據(jù)提交,那么表單到底是用什么方式來提交給服務器的呢?

引入:數(shù)據(jù)的提交本質(zhì)是利用HTTP協(xié)議進行數(shù)據(jù)提交,而HTTP協(xié)議考慮到數(shù)據(jù)的安全性和多樣性,也提供了多種數(shù)據(jù)提交規(guī)則。

表單傳值方式【掌握】

定義:傳值方式是HTTP協(xié)議根據(jù)動態(tài)網(wǎng)站的數(shù)據(jù)交互的要求,設定的一種傳輸規(guī)則。表單傳值則是HTML根據(jù)HTTP傳輸協(xié)議而設定的自己的數(shù)據(jù)傳輸規(guī)則。在HTTP協(xié)議中,傳輸規(guī)則有6種:HEAD、GET、PUT、POST、DELETE和OPTIONS,而HTML的表單傳值通常只用到2種,那就是GET和POST。

1.簡單介紹HTTP協(xié)議的傳輸規(guī)則

  • HEAD:通過發(fā)送HTTP請求來從服務器獲取數(shù)據(jù)(不帶任何數(shù)據(jù),很少使用)
  • GET:與HEAD一樣,但是GET通常是通過自身攜帶數(shù)據(jù)來獲取服務器數(shù)據(jù)
  • PUT:指定服務器端存儲位置來提交數(shù)據(jù)(HTML不支持)
  • POST:直接提交數(shù)據(jù)給服務器
  • DELETE:通過指定數(shù)據(jù)來刪除服務器的數(shù)據(jù)(很少使用)
  • OPTIONS:獲取URL所支持的方法(極少使用)

2.表單傳值方式:表單傳值為了方便開發(fā)人員開發(fā),通常只使用GET和POST兩種方式來實現(xiàn)數(shù)據(jù)的提交

  • GET:顯示的提交用戶數(shù)據(jù),通常開發(fā)人員認定此數(shù)據(jù)不會對后臺數(shù)據(jù)產(chǎn)生改變,只會通過提交的數(shù)據(jù)來確定服務器要返回的數(shù)據(jù)
  • POST:隱式的提交用戶數(shù)據(jù),通常該類數(shù)據(jù)都是用來存儲到后臺數(shù)據(jù)庫的

總結:HTTP協(xié)議雖然提供了多種傳輸數(shù)據(jù)的方式,但是在Web的實際開發(fā)中,只用到了其中的GET和POST兩種,因為這兩種已經(jīng)已經(jīng)足夠支撐Web開發(fā)中所需要的業(yè)務了。


思考:Web開發(fā)中用到了GET和POST兩種開發(fā)方式,那么這兩種開發(fā)方式是如何在實際開發(fā)的時候?qū)崿F(xiàn)的呢?

引入:GET和POST這兩種表單傳值方式,有的時候是非常明顯的體現(xiàn),但是有的時候可能就是比較隱性的體現(xiàn)。比如說GET的方式就比較多,而POST方式就比較單一。

GET和POST傳值實現(xiàn)【掌握】

定義:無論是GET還是POST都可以實現(xiàn)表單傳值,但是彼此之間有方式區(qū)別,也有安全的區(qū)別,還有人為(開發(fā)者)的使用區(qū)別。不管是哪種方式,都是由開發(fā)人員確定,終端操作用戶不能根據(jù)自己的想法來選擇。

1.GET傳值:GET傳值是一種比較顯性的數(shù)據(jù)傳輸方式,會在提交傳輸過程中,直接將數(shù)據(jù)添加到用戶可見的URL之后。GET傳值的方式有以下幾種:

  • a標簽傳輸:直接在a標簽中對應的href屬性對應的鏈接中添加數(shù)據(jù),數(shù)據(jù)的添加格式就是使用?將URL主體和數(shù)據(jù)分離,數(shù)據(jù)的綁定方式屬于鍵值對,即:名字=值,如果是多個數(shù)據(jù)使用&符號分離
<html>
<head></head>
<body>
<a >淘寶.筆記本.超極本</a>
<!--其中http://是協(xié)議,www.taobao.com屬于主機地址,/index.php是URI,而?之后都是對應的數(shù)據(jù):keywords和type都屬于數(shù)據(jù)的名字,筆記本和超極本屬于數(shù)據(jù)值,&符號代表多個數(shù)據(jù)的分隔符號-->
</body>
</html>

a標簽的傳輸方式是GET方式傳輸?shù)囊环N典型代表,幾乎所有的GET方式傳值都采用a標簽方式。a標簽的數(shù)據(jù)并非用戶提交,而是由后臺開發(fā)人員根據(jù)用戶的需求,提前準備好

  • form標簽:form標簽是HTML中專門針對用戶數(shù)據(jù)提交的一種表單,該表單允許會由開發(fā)人員提前準備好。form標簽本身不做任何數(shù)據(jù)傳輸,而是靠form表單內(nèi)部的其他數(shù)據(jù)表單來綁定數(shù)據(jù),form表單可以批量進行數(shù)據(jù)傳輸
<html>
<head></head>
<body>
<form action="請求腳本文件地址" method="GET">
<input type="text" name="keywords" value=""/>
<input type="text" name="type" value=""/>
<input type="submit" value="檢索"/>
<!--
    form中action代表的本次提交的目標屬性,即后臺某個能夠處理當前請求的PHP腳本;
    method是form的可改變屬性,如果為GET那么意味著提交方式為GET傳值,如果是POST那么就是POST傳值;
    input為表單框,type確定表單元素的操作屬性,text表明是文本輸入,submit為提交動作,name作為提交的必須屬性代表提交給后臺數(shù)據(jù)對應的數(shù)據(jù)名字,value代表數(shù)據(jù)值,用戶輸入的那么可以為空,由用戶輸入數(shù)據(jù)
-->
</form>
</body>
</html>

form表單是一種標準數(shù)據(jù)提交方式,可選GET方式還是POST方式,由開發(fā)人員根據(jù)當前數(shù)據(jù)的類型和數(shù)據(jù)的安全性來確定。通常如果是需要用戶進行數(shù)據(jù)寫入的時候就會使用到form表單,form表單不限定數(shù)據(jù)數(shù)量

  • location對象的href屬性:location是window對象的一個屬性,是用來包含當前窗口對應的url信息,但是同時該屬性本身還有一個href屬性,可以用來動態(tài)的改變窗口對應的url,這個時候需要利用事件
<html>
<head></head>
<body>
<input type="button" value="獲取當前URL" onclick="alert(window.location)"/>
<!--window.location會得到當前的URL-->
<input type="button" value="改變當前URL" onClick="window.location./>
<!--window.location.href會在觸發(fā)后進入到指定的url地址-->
</body>
</html>

window.location.href這個在實際開發(fā)中會更多應用于事件操作。即用戶在做某些指定操作的時候,可以進行頁面的跳轉(zhuǎn)

  • location對象的assign()方法:assign()方法與href屬性相似,都是需要通過事件操作來設定某些觸發(fā)點,然后用戶觸發(fā)后執(zhí)行對應的窗口跳轉(zhuǎn)
<html>
<head></head>
<body>
<input type="button" value="改變當前URL" onClick="window.location.assign('http://www.baidu.com/index.php?search=電腦')"/>
<!--window.location.href會在觸發(fā)后進入到指定的url地址-->
</body>
</html>

window.location.assign()的本質(zhì)與href屬性一樣,就是改變當前窗口的URL,其操作方式也是通過事件觸發(fā)
2.POST傳值:POST傳值是一種比較隱性的傳值方式,一般用戶無法直觀的看到傳輸?shù)臄?shù)據(jù),POST傳值方式比較單一,就是通過Form表單進行傳值,同時在method屬性中使用POST方式即可

<html>
<head></head>
<body>
<form action="請求腳本文件地址" method="POST">
<input type="text" name="keywords" value=""/>
<input type="text" name="type" value=""/>
<input type="submit" value="檢索"/>
</form>
</body>
</html>

3.GET與POST的區(qū)別:GET和POST沒有本質(zhì)的區(qū)別,都可以實現(xiàn)數(shù)據(jù)從瀏覽器端傳輸?shù)椒掌鞫?/p>

  • 目標用途區(qū)別:GET主要用來獲取服務器數(shù)據(jù),提供的是一些數(shù)據(jù)信息片段,服務器通過數(shù)據(jù)片段獲取數(shù)據(jù);POST主要用來提交數(shù)據(jù),即數(shù)據(jù)最終會實現(xiàn)數(shù)據(jù)庫的數(shù)據(jù)變更
  • 實現(xiàn)方式區(qū)別:GET可以使用URL、form表單和window.location來實現(xiàn)(本質(zhì)還是URL),而POST只能通過form表單實現(xiàn)
  • 執(zhí)行效果區(qū)別:GET傳值在提交時數(shù)據(jù)通常會在瀏覽器地址欄中顯示,而POST不會顯示(所以POST安全性比GET高)
  • 傳輸大小區(qū)別:理論上來講GET和POST沒有區(qū)別(HTTP協(xié)議沒有規(guī)定),但是瀏覽器通常在GET上做了限制,不同瀏覽器限制的大小不一樣,IE為2K,而POST依然沒有限制

總結:在Web開發(fā)中,通常使用HTTP協(xié)議中的GET和POST來實現(xiàn)用戶數(shù)據(jù)提交,GET和POST的應用有所區(qū)別,需要程序員根據(jù)實際需求、內(nèi)容和安全性等來選擇對應的方式。通常查看、刪除數(shù)據(jù)使用GET方式,新增和修改使用POST方式。


思考:瀏覽器提交數(shù)據(jù),其實還是服務器給用戶做好的,只是用戶根據(jù)具體數(shù)據(jù)需求來選擇是點擊、選擇還是輸入。那么當用戶把數(shù)據(jù)提交了以后,服務器端怎么處理呢?

引入:服務器端Apache是無法去獲取用戶提交的數(shù)據(jù)的,這些數(shù)據(jù)需要PHP來接收處理。而PHP默認就考慮到了實際開發(fā)的需求,因此提供了一些預定義變量(系統(tǒng)變量)來自動接收數(shù)據(jù)。

PHP接收數(shù)據(jù)【掌握】

定義:PHP接收數(shù)據(jù),其實就是根據(jù)HTTP協(xié)議的特點,將用戶按照HTTP協(xié)議提交的數(shù)據(jù)取出來存放到不同的容器(預定義變量)中,從而能夠方便開發(fā)者直接使用這些接收的數(shù)據(jù)。

1.在PHP中,為開發(fā)者提供了三種數(shù)據(jù)接收的方式,分別是:

  • $_GET:接收用戶GET方式提交的數(shù)據(jù)
  • $_POST:接收用戶POST方式提交的數(shù)據(jù)
  • $_REQUEST:接收用戶GET和POST提交的數(shù)據(jù)

2.$_GET:專用于接收GET方式提交的數(shù)據(jù),是一個超全局預定義數(shù)組,表單名字作為數(shù)組下標,表單值作為數(shù)組元素值

用戶提交數(shù)據(jù)的HTML文件
<html>
<head></head>
<body>
<a >淘寶.筆記本.超極本</a>
</body>
</html>

服務器接收數(shù)據(jù)的index.php文件
<?php
//輸出關鍵字和類型
echo $_GET['keywords'];        //筆記本
echo $_GET['type'];            //超極本
?>

3._POST:專用于接收POST方式提交的數(shù)據(jù),與_GET形式一樣

用戶提交數(shù)據(jù)的HTML文件:用戶輸入筆記本和超極本數(shù)據(jù)提交
<html>
<head></head>
<body>
<form action="index.php" method="POST">
<input type="text" name="keywords" value=""/>
<input type="text" name="type" value=""/>
<input type="submit" value="檢索"/>
</form>
</body>
</html>

服務器接收數(shù)據(jù)的index.php文件
<?php
//輸出數(shù)據(jù)
echo $_POST['keywords'];        //筆記本
echo $_GET['type'];             //超極本
?>

4.$_REQUEST:接收用戶使用GET和POST方式提交的數(shù)據(jù),但是因為PHP數(shù)組下標具有唯一性,如果GET和POST方式各有一個同名數(shù)據(jù),那么默認POST會覆蓋GET(通常不會同時出現(xiàn)GET和POST),也正是因為會存在數(shù)據(jù)覆蓋的情況,所以開發(fā)人員通常會明確到底是GET還是POST,只是在有的數(shù)據(jù)來源可能有多方面的時候會使用

用戶提交數(shù)據(jù)的HTML文件:用戶輸入筆記本和超極本數(shù)據(jù)提交
<html>
<head></head>
<body>
<form action="index.php?keywords=娃娃" method="POST">
<input type="text" name="keywords" value=""/>
<input type="text" name="type" value=""/>
<input type="submit" value="檢索"/>
</form>
</body>
</html>

服務器接收數(shù)據(jù)的index.php文件
<?php
//輸出數(shù)據(jù):POST
echo $_POST['keywords'];        //筆記本
echo $_POST['type'];             //超極本

//輸出數(shù)據(jù):GET
echo $_GET['keywords'];         //娃娃
echo $_GET['type'];             //錯誤:沒有該元素

//輸出數(shù)據(jù):REQUEST
echo $_REQUEST['keywords'];     //筆記本
echo $_REQUEST['type'];         //超極本
?>

5.練習:制作一個驗證用戶登錄的簡易表單,然后在后臺實現(xiàn)數(shù)據(jù)的接收與驗證(后臺固定用戶名和密碼:密碼MD5加密)

總結:實際開發(fā)中,開發(fā)人員是可以明確控制用戶數(shù)據(jù)的提交方式的,因此在后臺也會明確獲取數(shù)據(jù)的方式_GET和_POST,但是也會有特定情況下數(shù)據(jù)的來源不夠明確,因此要用到$_REQUEST來接收數(shù)據(jù)。


思考:在實際開發(fā)中,有些需求會涉及到用戶的多數(shù)據(jù)提交,比如單選框和復選框之類的,那么這類數(shù)據(jù)也是像普通表單一樣處理嗎?

引入:本質(zhì)上來講,如果這類復合表單數(shù)據(jù)也可以采用同樣的方式來提交數(shù)據(jù)和接收數(shù)據(jù)。但是如果一旦按照普通方式來處理,意味著可擴展性會變得很差,因此會針對這類需求進行特殊處理。

復合表單提交【掌握】

定義:復合表單是一類比較特殊的表單,包括單選框和復選框,這類對應的實際表單數(shù)據(jù)比較多(通常不止一個),而代表的數(shù)據(jù)通常是單一的,因此在這類處理的時候,通常為了方便操作,前后臺都會設置一個唯一的名字來進行規(guī)范

1.單選框操作:單選框即給用戶提供多個選擇,但是用戶只能選擇一個結果。即用戶表單有多個,但是最終提交給服務器的永遠只有一個。這類表單的處理方式比較簡單:表單多個,但是名字一致,后臺只需要接收一個結果。

單選框表單:一個名字,多個單選框表單
<html>
<head></head>
<body>
<form action="index.php" method="POST">
<input type="radio" name="gender" value="男"/>
<input type="radio" name="gender" value="女"/>
<input type="radio" name="gender" value="保密"/>
<input type="submit" value="提交"/>
</form>
</body>
</html>

服務器接收數(shù)據(jù)的index.php文件
<?php
//輸出接收結果
echo $_POST['gender'];            //用戶選中的一個具體值
?>

2.復選框操作:復選框同樣也是給定用戶多個選中,而且用戶也可以選中多個結果。這個時候就比較麻煩了,因為如果同名,PHP接收的時候會覆蓋同名表單,那么最終后臺只能保留一個用戶選擇。為了解決這個矛盾,就要利用HTML表單不識別[]而PHP會自動識別[]為數(shù)組的特性。

復選框表單:一個名字+[],多個復選框表單
<html>
<head></head>
<body>
<form action="index.php" method="POST">
<input type="checkbox" name="hobby[]" value="籃球"/>
<input type="checkbox" name="hobby[]" value="足球"/>
<input type="checkbox" name="hobby[]" value="臺球"/>
<input type="checkbox" name="hobby[]" value="乒乓球"/>
<input type="checkbox" name="hobby[]" value="羽毛球"/>
<input type="checkbox" name="hobby[]" value="排球"/>
<input type="submit" value="提交"/>
</form>
</body>
</html>

服務器接收數(shù)據(jù)的index.php文件
<?php
//輸出接收結果:$_POST接收到hobby[]變成$_POST[hobby[]],從而最終轉(zhuǎn)變成$_POST[hobby][]
var_dump($_POST['hobby']);            //array+具體元素個數(shù)
?>

3.數(shù)據(jù)回顯:很多時候,會涉及到數(shù)據(jù)編輯,這個時候就需要將用戶原來保存的數(shù)據(jù)在用戶進行編輯前顯示給用戶。顯示的方式通常也是以對應的復合表單方式顯示。其實復合表單回顯就是被選中,在HTML中提供了對應選中屬性:checked="checked"

<?php
//獲取用戶原來的數(shù)據(jù):假定從數(shù)據(jù)庫獲取
$gender = '男';
$hobby = ['籃球','乒乓球','羽毛球'];
?>

<!--HTML中顯示數(shù)據(jù)-->
<html>
<head></head>
<body>
<form action="index.php" method="POST">
<!--單選框后臺只保留一個值,所以直接比較即可:成功后輸出checked="checked"-->
<input type="radio" name="gender" <?php echo $gender == '男' ? 'checked="checked"' : '';?> value="男"/>
<input type="radio" name="gender" <?php echo $gender == '女' ? 'checked="checked"' : '';?> value="女"/>
<input type="radio" name="gender" <?php echo $gender == '保密' ? 'checked="checked"' : '';?> value="保密"/>

<!--復選框后臺保留的是數(shù)組,所以要采用存在判定-->
<input type="checkbox" name="hobby[]" <?php echo in_array('籃球',$hobby) ? 'checked="checked"' : '';?> value="籃球"/>
<input type="checkbox" name="hobby[]" <?php echo in_array('籃球',$hobby) ? 'checked="checked"' : '';?> value="足球"/>
<input type="checkbox" name="hobby[]" <?php echo in_array('籃球',$hobby) ? 'checked="checked"' : '';?> value="臺球"/>
<input type="checkbox" name="hobby[]" <?php echo in_array('籃球',$hobby) ? 'checked="checked"' : '';?> value="乒乓球"/>
<input type="checkbox" name="hobby[]" <?php echo in_array('籃球',$hobby) ? 'checked="checked"' : '';?> value="羽毛球"/>
<input type="checkbox" name="hobby[]" <?php echo in_array('籃球',$hobby) ? 'checked="checked"' : '';?> value="排球"/>
<input type="submit" value="提交修改"/>
</form>
</body>
</html>

4.練習:同時使用單選框和復選框制作一個用戶基本信息收集表單,然后在后臺接收數(shù)據(jù)并進行展示

總結:單選框和復選框這類復合表單要根據(jù)實際需求來設定表單、接收數(shù)據(jù)以及存儲數(shù)據(jù),其實本質(zhì)原因是為了良好的可擴展性(如復選框要增加一個元素只需要修改表單,不需要修改PHP代碼和數(shù)據(jù)庫設計)。而這種特性利用的就是單選框的唯一性和復選框的[]不識別特性(PHP識別特性)。


思考:文件上傳的時候是不是也是給用戶提供對應的表單,然后后臺用_POST或者_GET去接收操作呢?

引入:文件上傳的操作比較復雜,不是簡單的上傳-接收過程。因為接收文件是需要利用到操作系統(tǒng)來實現(xiàn)的,同時文件對應的信息也比較多,需要使用特定的方式來接收處理。

文件上傳操作【掌握】

定義:文件上傳,是指給定用戶提供文件上傳表單,用戶將文件從本機電腦上傳到服務器的過程,而且這個過程需要借助操作系統(tǒng)作為中間媒介來完成。

1.制作文件上傳表單:文件上傳表單理論上只需要借助于input標簽中的file類型來實現(xiàn),且表單必須為post方式上傳(文件通常比較大)。但是還有一個特殊問題,就是文件是二進制的不是普通字符流,所以需要明確告知HTTP協(xié)議使用到了文件上傳,這時需要在表單form中使用屬性enctype,enctype是關于表單內(nèi)容處理的屬性:

  • enctype='application/x-www-form-urlencoded',默認屬性值,表示在發(fā)送前對所有特殊字符進行編碼(對應ASCII)
  • enctype='multipart/form-data',表示不對數(shù)據(jù)進行編碼(二進制不用編碼)
  • enctype="text/plain",只對空格進行轉(zhuǎn)換,變成“+”,其他不編碼
<html>
<head></head>
<body>
<form action="處理文件上傳的PHP文件" method="POST" enctype="multipart/form-data">
<input type="file" name="file" value=""/>
<!--name屬性為后臺接收名字,value可以為空-->
<input type="submit" name="submit" value="上傳"/>
</form>
</body>
</html>

2.PHP接收:默認的如果不使用enctype屬性,那么文件上傳是偽成功的:即PHP可以使用_POST接收到該表單,但是僅僅是表單的名字和文件的名字而已,不是真正的文件上傳。一旦加上enctype屬性,可以使用_FILES來接收文件

<?php
//取出文件
$file = $_FILES['file'];        //file下標為表單中name屬性的值
?>

3.文件上傳后,在PHP端會保存文件的5個信息

  • name:文件在客戶端本地的文件名字
  • type:文件的類型(MIME類型:多功能互聯(lián)網(wǎng)郵件擴展)
  • tmp_name:文件在服務器端操作系統(tǒng)接收后保存的臨時文件名字:默認是操作系統(tǒng)的臨時文件存儲目錄(可以通過PHP配置文件修改)
  • error:錯誤代碼
PHP文件上傳錯誤代碼描述.png
  • size:文件大小(字節(jié))

4.文件是操作系統(tǒng)臨時接收的,保存在臨時文件中。PHP如果不處理,那么操作系統(tǒng)就會認為數(shù)據(jù)沒有意義,自動清除。因此PHP需要將臨時文件進行目標轉(zhuǎn)移,轉(zhuǎn)移到指定位置,使用函數(shù):move_uploaded_file(臨時文件路徑,目標存儲位置),目標存儲位置需要重命名(默認臨時文件名字為tmp)

fileupload.php

<?php

//文件上傳函數(shù)封裝
/*
 * @param1 array $file,要上傳的文件信息,包含5個元素
 * @param2 string $path,存儲位置
 * @param3 string &error,錯誤信息
 * @param4 array $type = array(),MIME類型限定
 * @param5 int $size = 2000000,默認2M
 * @return mixed ,成功返回文件名字,失敗返回false
 */
function fileupload($file,$path,&$error,$type = array(),$size = 2000000){
    //1判定文件本身是有效文件
    if(!isset($file['error'])){
        $error = '文件無效';
        return false;
    }

    //2.有效路徑判定
    if(!is_dir($path)){
        $error = '存儲路徑無效';
        return false;
    }

    //3.判定文件本身上傳是否成功
    switch ($file['error']) {
        case 1:
        case 2:
            $error = '文件超過服務器允許大小';
            return false;
        case 3:
            $error = '文件只有部分成功';
            return false;
        case 4:
            $error = '用戶沒有選擇要上傳的文件';
            return false;
        case 6:
        case 7:
            $error = '服務器操作失敗';
            return false;
    }

    //4.判定類型是否符合
    if(!empty($type) && !in_array($file['type'],$type)){
        $error = '當前上傳的文件類型不符合';
        return false;
    }

    //5.大小判定
    if($file['size'] > $size){
        $error = '文件大小超過當前允許范圍.當前允許的大小是:' . string($size/1000000) . 'M.';
        return false;
    }

    //6.移動文件:轉(zhuǎn)存
    $newfilename = getNewName($file['name']);
    if(@move_uploaded_file($file['tmp_name'], $path . '' . $newfilename)){
        //成功
        return $newfilename;
    }else{
        $error = '文件上傳失敗';
        return false;
    }
}

//構造一個文件名字:隨機規(guī)則
function getNewName($filename,$rand = 6){
    //1.時間日期部分
    $newname = date('YmdHis');

    //2.增加隨機部分
    $old = array_merge(range('a','z'),range('A','Z')); 
    shuffle($old);
    for($i = 0;$i < $rand;$i++){
        $newname .= $old[$i];
    }

    //3.組織有效文件名
    return $newname . strstr($filename,'.');
}
?>

調(diào)用封裝好的函數(shù)

<?php


//接收文件
$file = $_FILES['file'];

//判定錯誤
/*if($file['error'] == 0){
    //已經(jīng)成功了在服務器端
    move_uploaded_file($file['tmp_name'],'UPLOAD/' . $file['name']);
}*/

//調(diào)用文件上傳函數(shù)實現(xiàn)
include_once 'fileupload.php';

$res = fileupload($file,'UPLOAD/',$error);

if($res){
    echo '文件上傳成功!';
}else{
    echo $error;
}
<?php

//查看post數(shù)據(jù)
//var_dump($_POST);

//查看文件數(shù)據(jù)
//var_dump($_FILES);

//接收文件
$file = $_FILES['file'];

//判定錯誤
/*if($file['error'] == 0){
    //已經(jīng)成功了在服務器端
    move_uploaded_file($file['tmp_name'],'UPLOAD/' . $file['name']);
}*/

//調(diào)用文件上傳函數(shù)實現(xiàn)
include_once 'fileupload.php';

$res = fileupload($file,'UPLOAD/',$error);

if($res){
    echo '文件上傳成功!';
}else{
    echo $error;
}

6.練習:封裝文件上傳函數(shù),然后利用文件上傳函數(shù)實現(xiàn)文件上傳

總結:文件上傳是Web開發(fā)中很重要的一個功能,幾乎所有涉及用戶管理的網(wǎng)站,都會用到文件上傳功能。而這項功能本身并不復雜,只有三個部分:用戶選擇文件上傳(表單)-》PHP判定文件安全($_FILES判定)-》文件移動保存(save_uploaded_file)


思考:在很多網(wǎng)站中,都會看到有文件上傳的功能,很多的時候可能要一次性操作很多文件,這個時候該怎么處理呢?

引入:文件上傳理論上只是一個一個上傳,所謂的批量上傳到了服務器端也是一個一個上傳的,只是用戶的感覺是一次性上傳多個的。不過在多文件上傳的時候,也會涉及到兩種不同的需求。

多文件上傳【掌握】

定義:所謂多文件上傳,只是從用戶的角度進行一次性多個文件上傳而已。但是后臺的本質(zhì)依然是一個文件一個文件的上傳,但是因為PHP效率問題,用戶感覺不到什么延遲效果。

1.多文件上傳根據(jù)上傳文件的方式有兩種分別:

  • 有多處需要文件上傳,而每個文件之間沒有什么關聯(lián),這類的本質(zhì)依然單文件上傳
<html>
<head></head>
<body>
<form action="處理文件上傳的PHP文件" method="POST" enctype="multipart/form-data">
頭像:<input type="file" name="head_img" value=""/>
身份證正面照:<input type="file" name="id_img1" value=""/>
身份證反面照:<input type="file" name="id_img2" value=""/>
<input type="submit" name="submit" value="上傳"/>
</form>
</body>
</html>
  • 在同一個地方需要有多個文件上傳,多個文件屬于同一類文件,需要共同管理:這類表單利用的與復選框命名方式類似
<html>
<head></head>
<body>
<form action="處理文件上傳的PHP文件" method="POST" enctype="multipart/form-data">
個人相冊:
<input type="file" name="photo[]" value=""/>
<input type="file" name="photo[]" value=""/>
<input type="file" name="photo[]" value=""/>
<input type="submit" name="submit" value="上傳"/>
</form>
</body>
</html>

2.多文件后臺PHP處理

  • 對于多個單文件上傳,后臺可以直接利用已經(jīng)封裝好的文件上傳函數(shù)多次調(diào)用即可
<?php
//循環(huán)調(diào)用函數(shù):因為一個文件就會在$_FILES中形成一個元素
foreach($_FILES as $file){
    //$file就是每一個元素:對應一個上傳文件的5要素
    $res = uploadFile($file,'文件保存路徑',$error);
    if($res === false){
        //上傳失敗
        exit($error);
    }
        
    //提升上傳成功
    echo "文件:" . $file['name'] . ' 上傳成功!';

}
?>
  • 對于同名多文件上傳,那么$_FILES接收的數(shù)據(jù)是生成5個元素的二維數(shù)組,因此需要將每個文件的5個要素取出來獨立成一個文件信息,然后使用單文件上傳即可。
<?php
//通過任意一個要素長度來進行循環(huán)
for($i = 0,$len = count($_FILES['photo']['error']);$i < $len;$i++){
    //因為同名元素長傳,導致的結果是error\name\size\tmp_name\type都各自形成一個索引數(shù)組
    //構造每個文件信息:關聯(lián)數(shù)組
    $file = array(
        'name' => $_FILES['photo']['name'][$i],
        'type' => $_FILES['photo']['type'][$i],
        'tmp_name' => $_FILES['photo']['tmp_name'][$i],
        'error' => $_FILES['photo']['error'][$i],
        'size' => $_FILES['photo']['size'][$i]
    );
    
    //調(diào)用文件上傳
    uploadFile($file,'文件上傳路徑',$error);
}
?>

3.練習:制作一個單文件上傳函數(shù),也制作一個多文件上傳函數(shù),使用多文件上傳函數(shù)調(diào)用單文件函數(shù)上傳,最終實現(xiàn)多文件上傳。

總結:文件上傳是Web開發(fā)中必不可少的一個需求,文件上傳要后臺把控的地方比較多,需要注意每一個細節(jié)的驗證,保證服務器的安全。多文件上傳最終其實也是歸屬到單文件上傳,要掌握多文件上傳的細節(jié),然后轉(zhuǎn)換成單文件上傳即可。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容