整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          手把手教你前端的各種文件上傳攻略和大文件斷點續(xù)傳



          在前面

          今年國慶假期終于可以憋在家里了不用出門了,不用出去看后腦了,真的是一種享受。這么好的光陰怎么浪費,睡覺、吃飯、打豆豆這怎么可能(耍多了也煩),完全不符合我們程序員的作風(fēng),趕緊起來把文章寫完。

          這篇文章比較基礎(chǔ),在國慶期間的業(yè)余時間寫的,這幾天又完善了下,力求把更多的前端所涉及到的關(guān)于文件上傳的各種場景和應(yīng)用都涵蓋了,若有疏漏和問題還請留言斧正和補充。

          自測讀不讀

          以下是本文所涉及到的知識點,break or continue ?

          • 文件上傳原理
          • 最原始的文件上傳
          • 使用 koa2 作為服務(wù)端寫一個文件上傳接口
          • 單文件上傳和上傳進度
          • 多文件上傳和上傳進度
          • 拖拽上傳
          • 剪貼板上傳
          • 大文件上傳之分片上傳
          • 大文件上傳之斷點續(xù)傳
          • node 端文件上傳

          原理概述

          原理很簡單,就是根據(jù) http 協(xié)議的規(guī)范和定義,完成請求消息體的封裝和消息體的解析,然后將二進制內(nèi)容保存到文件。

          我們都知道如果要上傳一個文件,需要把 form 標簽的enctype設(shè)置為multipart/form-data,同時method必須為post方法。

          那么multipart/form-data表示什么呢?

          multipart互聯(lián)網(wǎng)上的混合資源,就是資源由多種元素組成,form-data表示可以使用HTML Forms 和 POST 方法上傳文件,具體的定義可以參考RFC 7578。

          multipart/form-data 結(jié)構(gòu)

          看下 http 請求的消息體



          • 請求頭:

          Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryDCntfiXcSkPhS4PN 表示本次請求要上傳文件,其中boundary表示分隔符,如果要上傳多個表單項,就要使用boundary分割,每個表單項由———XXX開始,以———XXX結(jié)尾。

          • 消息體- Form Data 部分

          每一個表單項又由Content-Type和Content-Disposition組成。

          Content-Disposition: form-data 為固定值,表示一個表單元素,name 表示表單元素的 名稱,回車換行后面就是name的值,如果是上傳文件就是文件的二進制內(nèi)容。

          Content-Type:表示當前的內(nèi)容的 MIME 類型,是圖片還是文本還是二進制數(shù)據(jù)。

          解析

          客戶端發(fā)送請求到服務(wù)器后,服務(wù)器會收到請求的消息體,然后對消息體進行解析,解析出哪是普通表單哪些是附件。

          可能大家馬上能想到通過正則或者字符串處理分割出內(nèi)容,不過這樣是行不通的,二進制buffer轉(zhuǎn)化為string,對字符串進行截取后,其索引和字符串是不一致的,所以結(jié)果就不會正確,除非上傳的就是字符串。

          不過一般情況下不需要自行解析,目前已經(jīng)有很成熟的三方庫可以使用。

          至于如何解析,這個也會占用很大篇幅,后面的文章在詳細說。

          最原始的文件上傳

          使用 form 表單上傳文件

          在 ie時代,如果實現(xiàn)一個無刷新的文件上傳那可是費老勁了,大部分都是用 iframe 來實現(xiàn)局部刷新或者使用 flash 插件來搞定,在那個時代 ie 就是最好用的瀏覽器(別無選擇)。

          DEMO



          這種方式上傳文件,不需要 js ,而且沒有兼容問題,所有瀏覽器都支持,就是體驗很差,導(dǎo)致頁面刷新,頁面其他數(shù)據(jù)丟失。

          HTML

           <form method="post" action="http://localhost:8100" enctype="multipart/form-data">
          
                  選擇文件:
                      <input type="file" name="f1"/> input 必須設(shè)置 name 屬性,否則數(shù)據(jù)無法發(fā)送<br/>
          <br/>
                      標題:<input type="text" name="title"/><br/><br/><br/>
          
                  <button type="submit" id="btn-0">上 傳</button>
          
          </form>
          
          復(fù)制代碼

          文件上傳接口

          服務(wù)端文件的保存基于現(xiàn)有的庫koa-body結(jié)合 koa2實現(xiàn)服務(wù)端文件的保存和數(shù)據(jù)的返回。

          在項目開發(fā)中,文件上傳本身和業(yè)務(wù)無關(guān),代碼基本上都可通用。

          在這里我們使用koa-body庫來實現(xiàn)解析和文件的保存。

          koa-body 會自動保存文件到系統(tǒng)臨時目錄下,也可以指定保存的文件路徑。



          然后在后續(xù)中間件內(nèi)得到已保存的文件的信息,再做二次處理。

          • ctx.request.files.f1 得到文件信息,f1為input file 標簽的 name
          • 獲得文件的擴展名,重命名文件

          NODE

          /**
           * 服務(wù)入口
           */
          var http = require('http');
          var koaStatic = require('koa-static');
          var path = require('path');
          var koaBody = require('koa-body');//文件保存庫
          var fs = require('fs');
          var Koa = require('koa2');
          
          var app = new Koa();
          var port = process.env.PORT || '8100';
          
          var uploadHost= `http://localhost:${port}/uploads/`;
          
          app.use(koaBody({
              formidable: {
                  //設(shè)置文件的默認保存目錄,不設(shè)置則保存在系統(tǒng)臨時目錄下  os
                  uploadDir: path.resolve(__dirname, '../static/uploads')
              },
              multipart: true // 開啟文件上傳,默認是關(guān)閉
          }));
          
          //開啟靜態(tài)文件訪問
          app.use(koaStatic(
              path.resolve(__dirname, '../static') 
          ));
          
          //文件二次處理,修改名稱
          app.use((ctx) => {
              var file = ctx.request.files.f1;//得道文件對象
              var path = file.path;
              var fname = file.name;//原文件名稱
              var nextPath = path+fname;
              if(file.size>0 && path){
                  //得到擴展名
                  var extArr = fname.split('.');
                  var ext = extArr[extArr.length-1];
                  var nextPath = path+'.'+ext;
                  //重命名文件
                  fs.renameSync(path, nextPath);
              }
              //以 json 形式輸出上傳文件地址
              ctx.body = `{
                  "fileUrl":"${uploadHost}${nextPath.slice(nextPath.lastIndexOf('/')+1)}"
              }`;
          });
          
          /**
           * http server
           */
          var server = http.createServer(app.callback());
          server.listen(port);
          console.log('demo1 server start ......   ');
          復(fù)制代碼

          CODE

          https://github.com/Bigerfe/fe-learn-code/

          單的工作過程

          表單的信息發(fā)送與處理過程可以簡單的進行圖示,如下圖。

          以注冊會員為例,用戶在自己的電腦上打開相應(yīng)的注冊表單頁面填寫信息,完成填寫后點擊提交按鈕,也就是圖中1所示過程。

          這時瀏覽器會將這些信息發(fā)送給處理這些信息的服務(wù)器,服務(wù)器上有使用類似asp或php寫成的相應(yīng)的處理程序,處理完成后,生成一個反饋信息,也就是2到3的過程。

          然后服務(wù)器將處理后的信息發(fā)送給個人電腦,個人電腦在瀏覽器上通過一個新頁面來提示用戶處理結(jié)果。

          這里就涉及到一個問題,一個網(wǎng)站會有針對不同用戶的信息注冊表單以及相應(yīng)的信息處理程序,比如我們注冊頭條號就有"個人"、"企業(yè)"、"媒體"和"國家機構(gòu)"的區(qū)分。如何使不同的表單找到相應(yīng)的處理程序呢?在<form>標簽中,有一個action屬性就是為這個表單信息指定處理程序的。

          <form>中的action屬性

          調(diào)用程序

          <form>的action屬性實際上就是為表單提示處理程序所在的路徑,如果程序和頁面在一個服務(wù)器中存儲,那使用相對路徑即可,如果在其他服務(wù)器,則要使用絕對路徑。示例代碼如下:

          <form action="form_action.asp" method="get">
          <p>First name: <input type="text" name="fname" /></p> 
          <p>Last name: <input type="text" name="lname" /></p> 
          <input type="submit" value="Submit" />
          </form>

          這段代碼中的"form_action.asp"程序和這個表單頁面在一個文件夾中,故直接寫名稱即可調(diào)用。

          發(fā)送郵件

          action屬性除了調(diào)用程序外,也可以發(fā)送郵件,示例代碼如下:

          <form action="MAILTO:someone@w3school.com.cn" method="post" enctype="text/plain">
          <h3>這個表單會把電子郵件發(fā)送到 W3School。</h3>
          姓名:<br />
          <input type="text" name="name" value="yourname" size="20"><br />
          電郵:<br /><input type="text" name="mail" value="yourmail" size="20"><br />
          內(nèi)容:<br /><input type="text" name="comment" value="yourcomment" size="40"><br /><br />
          <input type="submit" value="發(fā)送">
          <input type="reset" value="重置">
          </form>

          這段代碼中。發(fā)送郵件的寫法是這樣的:action="MAILTO:someone@w3school.com.cn",通過MAILTO:告訴瀏覽器,這里要發(fā)送郵件!然后輸入相應(yīng)的郵箱地址,這樣就會把表單中的信息以郵件的形式發(fā)送到相應(yīng)的郵箱中了。

          大家可以把郵箱地址改成自己的郵箱試一下,瀏覽器會讓大家選擇發(fā)送郵件的程序。如圖所示:

          使用這個功能我們可以寫一個簡單的郵件發(fā)送頁面,示例代碼如下:

          <form action="mailto:yourname@domain.com" method="post" enctype="text/plain">
          主題:<input name="subject" type="text"><br>
          抄送:<input name="cc" type="text"><br>
          密送:<input name="bcc" type="text"><br>
          正文:<textarea name="body"></textarea><br>
          <input type="submit">
          </form>

          這樣的寫法大家可能會發(fā)現(xiàn)問題,即如果一個網(wǎng)站注冊用戶超過100人以后,靠這種手動輸入用戶郵箱的方法發(fā)送郵件簡直就是折磨人啊!

          實際上,在網(wǎng)站中,我們會把會員或注冊用戶的郵箱存在數(shù)據(jù)庫中,通過調(diào)用數(shù)據(jù)庫中的用戶郵箱的程序語句來替換action中的具體郵箱地址即可,再通過程序,可以針對全部用戶或部分用戶進行群發(fā)信息。

          其中,enctype屬性是向服務(wù)器聲明上傳信息的形式,也就是向服務(wù)器說明發(fā)送的數(shù)據(jù)到底是數(shù)字還是英文還是中文還是編程語句。專業(yè)一些的說法是"規(guī)定在發(fā)送表單數(shù)據(jù)之前如何對其進行編碼。"

          全部屬性值有三個,如圖所示,大家可以簡要理解一下。

          除此之外,我們還發(fā)現(xiàn)一個屬性叫做method(方法),通過上面的示例代碼可知,method屬性有兩個屬性值,一個是get一個是post,這是什么意思呢?

          信息上傳的兩種方法

          <form>中的method標簽即為表單信息指定相應(yīng)的發(fā)送方法。

          方法有兩種,一種叫g(shù)et,這種方法通常用來發(fā)送簡短的且低安全要求的信息,特點是速度比較快。

          post經(jīng)常用來發(fā)送體積較大的信息,如果發(fā)送一些對安全性要求高的信息,html的官方說明中建議使用post方法。

          我個人認為,現(xiàn)階段大家能記住這兩個方法的主要特點即可。這一篇的內(nèi)容實際上也是前端學(xué)習(xí)者對服務(wù)器端的運行的了解內(nèi)容。

          下面為大家附上更為專業(yè)的講解,看不懂也沒關(guān)系,盡量讀,至少能被專業(yè)詞匯洗禮一下!

          method 屬性

          瀏覽器使用 method 屬性設(shè)置的方法將表單中的數(shù)據(jù)傳送給服務(wù)器進行處理。共有兩種方法:POST 方法和 GET 方法。

          如果采用 POST 方法,瀏覽器將會按照下面兩步來發(fā)送數(shù)據(jù)。首先,瀏覽器將與 action 屬性中指定的表單處理服務(wù)器建立聯(lián)系,一旦建立連接之后,瀏覽器就會按分段傳輸?shù)姆椒▽?shù)據(jù)發(fā)送給服務(wù)器。

          在服務(wù)器端,一旦 POST 樣式的應(yīng)用程序開始執(zhí)行時,就應(yīng)該從一個標志位置讀取參數(shù),而一旦讀到參數(shù),在應(yīng)用程序能夠使用這些表單值以前,必須對這些參數(shù)進行解碼。用戶特定的服務(wù)器會明確指定應(yīng)用程序應(yīng)該如何接受這些參數(shù)。

          另一種情況是采用 GET 方法,這時瀏覽器會與表單處理服務(wù)器建立連接,然后直接在一個傳輸步驟中發(fā)送所有的表單數(shù)據(jù):瀏覽器會將數(shù)據(jù)直接附在表單的 action URL 之后。這兩者之間用問號進行分隔。

          一般瀏覽器通過上述任何一種方法都可以傳輸表單信息,而有些服務(wù)器只接受其中一種方法提供的數(shù)據(jù)。可以在 <form> 標簽的 method (方法)屬性中指明表單處理服務(wù)器要用方法來處理數(shù)據(jù),使 POST 還是 GET。

          POST 還是 GET?

          如果表單處理服務(wù)器既支持 POST 方法又支持 GET 方法,那么你該選擇哪種方法呢?下面是有關(guān)這方面的一些規(guī)律:

          如果希望獲得最佳表單傳輸性能,可以采用 GET 方法發(fā)送只有少數(shù)簡短字段的小表單。

          一些服務(wù)器操作系統(tǒng)在處理可以立即傳遞給應(yīng)用程序的命令行參數(shù)時,會限制其數(shù)目和長度,在這種情況下,對那些有許多字段或是很長的文本域的表單來說,就應(yīng)該采用 POST 方法來發(fā)送。

          如果你在編寫服務(wù)器端的表單處理應(yīng)用程序方面經(jīng)驗不足,應(yīng)該選擇 GET 方法。如果采用 POST 方法,就要在讀取和解碼方法做些額外的工作,也許這并不很難,但是也許你不太愿意去處理這些問題。

          如果安全性是個問題,那么我們建議選用 POST 方法。GET 方法將表單參數(shù)直接放在應(yīng)用程序的 URL 中,這樣網(wǎng)絡(luò)窺探者可以很輕松地捕獲它們,還可以從服務(wù)器的日志文件中進行摘錄。如果參數(shù)中包含了信用卡帳號這樣的敏感信息,就會在不知不覺中危及用戶的安全。而 POST 應(yīng)用程序就沒有安全方面的漏洞,在將參數(shù)作為單獨的事務(wù)傳輸給服務(wù)器進行處理時,至少還可以采用加密的方法。

          如果想在表單之外調(diào)用服務(wù)器端的應(yīng)用程序,而且包括向其傳遞參數(shù)的過程,就要采用 GET 方法,因為該方法允許把表單這樣的參數(shù)包括進來作為 URL 的一部分。而另一方面,使用 POST 樣式的應(yīng)用程序卻希望在 URL 后還能有一個來自瀏覽器額外的傳輸過程,其中傳輸?shù)膬?nèi)容不能作為傳統(tǒng) <a> 標簽的內(nèi)容。

          以上內(nèi)容來自W3school

          今天的內(nèi)容結(jié)束了,這一篇內(nèi)容實踐的東西比較少,主要是閱讀與了解。

          至此,HTML表單部分的講解就算告于段落了,如果您有任何疑問請給我留言,如有問題或錯誤請予以斧正!

          如果您喜歡我的教程請關(guān)注我,點贊也能讓我充滿動力!

          HTML完整學(xué)習(xí)目錄

          HTML序章(學(xué)習(xí)目的、對象、基本概念)——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          HTML是什么?——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          第一個HTML頁面如何寫?——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          HTML頁面中head標簽有啥用?——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          初識meta標簽與SEO——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          HTML中的元素使用方法1——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          HTML中的元素使用方法2——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          HTML元素中的屬性1——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          HTML元素中的屬性2(路徑詳解)——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          使用HTML添加表格1(基本元素)——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          使用HTML添加表格2(表格頭部與腳部)——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          使用HTML添加表格3(間距與顏色)——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          使用HTML添加表格4(行顏色與表格嵌套)——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          16進制顏色表示與RGB色彩模型——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          HTML中的塊級元素與內(nèi)聯(lián)元素——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          初識HTML中的<div>塊元素——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          在HTML頁面中嵌入其他頁面的方法——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          封閉在家學(xué)網(wǎng)頁制作!為頁面嵌入PDF文件——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          HTML表單元素初識1——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          HTML表單元素初識2——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          HTML表單3(下拉列表、多行文字輸入)——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          HTML表單4(form的action、method屬性)——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          HTML列表制作講解——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          為HTML頁面添加視頻、音頻的方法——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          音視頻格式轉(zhuǎn)換神器與html視頻元素加字幕——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          HTML中使用<a>標簽實現(xiàn)文本內(nèi)鏈接——零基礎(chǔ)自學(xué)網(wǎng)頁制作

          在開篇

          什么是表單呢?當前端想要提交數(shù)據(jù)給后端,怎么搞?那么在前端開發(fā)中,表單是常用的手段,比如常見的場景有:登錄框、賬號注冊頁、主機信息錄入CMDB等等場景都是需要表單。那么在本篇中,筆者除了講一些基本的知識點,還會再結(jié)合后端的方式來演示如何接收表單提交的數(shù)據(jù)。希望這些小小的演示可以起到拋磚引玉的效果。

          盤點HTML表單基礎(chǔ)

          1. from元素

          構(gòu)建表單,主要是通過from元素,我們先來一個最簡單的小栗子,看下面代碼:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <h3>主機信息錄入CMDB</h3>
                  <form>
                      <label for="hostname">主機名:</label><br>
                      <input type="text" id="hostname" name="hostname"><br>
                      <label for="ipaddr">IP地址:</label><br>
                      <input type="text" id="ipaddr" name="ipaddr"><br>
                      <input type="submit" value="提交">
                  </form>
              </body>
          </html>
          

          效果如下圖:

          通上面的小栗子可以知道,form表單的主要通途是用于收集用戶的輸入。在from表單里面,還包含著各種不同類型的input元素,比如我們上面小栗子中用到的文本(text)、提交按鈕(submit)。

          input元素是表單里最重要的元素,它有很多type屬性,下面我們來總結(jié)下:

          類型描述text文本輸入radio單選按鈕checkbox提交按鈕submit提交按鈕button可單擊按鈕

          在上面小栗子中,除了input元素之外,不知道大家注意label元素沒有。label元素的主要用途是為input元素定義標簽,且用for屬性和input元素的id屬性進行綁定呢。

          2. 單選按鈕

          什么是單選按鈕?就是在多個選項中,你只能選其中1個,不能多選。下面我們看個小栗子,看下面代碼:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <h3>問答題1(單選):某站長,工作經(jīng)驗不足1年,僅從互聯(lián)網(wǎng)收集學(xué)習(xí)資料制定學(xué)習(xí)路線售賣盈利,從道德層面角度分析是否有問題?</h3>
                  <form>
                      <input type="radio" id="i1" name="problem" value="yes">
                      <label for="i1">有</label>
                      <input type="radio" id="i2" name="problem" value="no">
                      <label for="i2">沒有</label>
                      <input type="radio" id="i3" name="problem" value="not_clear">
                      <label for="i3">不清楚</label>
                  </form>
                  <h3>問答題2(單選):實際工作經(jīng)驗不足1年的人員折騰的學(xué)習(xí)資料您覺得是否對你有幫助?</h3>
                  <form>
                      <input type="radio" id="w1" name="problem" value="yes">
                      <label for="w1">有</label>
                      <input type="radio" id="w2" name="problem" value="no">
                      <label for="w2">沒有</label>
                      <input type="radio" id="w3" name="problem" value="not_clear">
                      <label for="w3">不清楚</label>
                  </form>
              </body>
          </html>
          

          效果如下圖:

          上面的小栗子中,出了兩道問答題,均為單選題。那么,類似的需求都是可以使用輸入類型為radio來實現(xiàn)需要使用單選按鈕的場景。

          3. 復(fù)選框

          什么是復(fù)選框?復(fù)選框就是可以選擇多個選項,當需要多選的時候,使用復(fù)選框輸入類型就對了。看下面代碼:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <h3>問答題1(單選):某站長,工作經(jīng)驗不足1年,僅從互聯(lián)網(wǎng)收集學(xué)習(xí)資料制定學(xué)習(xí)路線售賣盈利,從道德層面角度分析是否有問題?</h3>
                  <form>
                      <input type="checkbox" id="i1" name="problem" value="yes">
                      <label for="i1">有</label>
                      <input type="checkbox" id="i2" name="problem" value="no">
                      <label for="i2">沒有</label>
                      <input type="checkbox" id="i3" name="problem" value="not_clear">
                      <label for="i3">不清楚</label><br>
                      <input type="submit" value="提交">
                  </form>
                  <h3>問答題2(單選):實際工作經(jīng)驗不足1年的人員折騰的學(xué)習(xí)資料您覺得是否對你有幫助?</h3>
                  <form>
                      <input type="checkbox" id="w1" name="problem" value="yes">
                      <label for="w1">有</label>
                      <input type="checkbox" id="w2" name="problem" value="no">
                      <label for="w2">沒有</label>
                      <input type="checkbox" id="w3" name="problem" value="not_clear">
                      <label for="w3">不清楚</label><br>
                      <input type="submit" value="提交">
                  </form>
              </body>
          </html>
          

          效果如下圖:

          上面的小栗子中,實現(xiàn)復(fù)選框的輸入類型是checkbox,這個是重點哦!

          4. 提交按鈕

          當有數(shù)據(jù)要提交給后端的時候怎么搞?如果后端是API服務(wù),可以給它提交json。如果是前端頁面,就需要通過構(gòu)建表單來獲取用戶的輸入。基于表單提交數(shù)據(jù)給后端,怎么提交?需要一個可以點擊的提交按鈕,那這個按鈕怎么來?先看下面代碼:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <h3>主機信息</h3>
                  <form>
                      <label for="ipaddr">IP地址</label>
                      <input type="text" id="ipaddr" name="ip"><br>
                      <input type="submit" value="提交">
                  </form>
              </body>
          </html>
          

          效果如下圖:

          輸入類型為submit,說明它就是提交按鈕,注意上面代碼type="submit"了嗎?

          HTML表單重要屬性

          1. Action屬性

          在之前的例子中,前端表單需要將數(shù)據(jù)提交給后端,除了需要一個提交按鈕外,還需要action屬性。當點擊提交按鈕后,表單的數(shù)據(jù)該發(fā)到后端的哪個url進行處理,就是定義在action屬性中。接下來,我們結(jié)合前端和后端直接來個小實戰(zhàn),后端代碼用Python的Flask框架。

          前端代碼:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <h3>主機信息</h3>
                  <form action="http://192.168.11.10:8088/ttropsstack" target="_blank">
                      <label for="ipaddr">IP地址</label>
                      <input type="text" id="ipaddr" name="ip"><br>
                      <input type="submit" value="提交">
                  </form>
              </body>
          </html>
          

          后端代碼:

          from flask import Flask, request
          
          webapp = Flask(__name__)
          
          @webapp.route('/ttropsstack', methods=["GET", "POST"])
          def ttropsstack():
              args = request.args
              print 'ip addr is: %s' % args.get('ip')
              return 'ok'
          
          if __name__ == '__main__':
          
              webapp.run(host="0.0.0.0", port=8088, debug=True)
          

          前端和后端的代碼寫完后,我們接下來看看效果

          輸入IP地址后,點擊提交

          這個ok是后端返回的

          后端接收到數(shù)據(jù)后,啥也沒做,只是做了簡單打印

          這個小栗子很簡單,通過這個小栗子,是不是對action屬性的用法有了進一步的理解呢?

          2. Method屬性

          method屬性的用途是指定提交數(shù)據(jù)的http方法,通常有2個,get和post。接下來我們在上個小栗子的基礎(chǔ)上做個小改造,看下面代碼

          前端代碼:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <h3>主機信息</h3>
                  <form action="http://192.168.11.10:8088/ttropsstack" target="_blank" method="get">
                      <label for="ipaddr">IP地址</label>
                      <input type="text" id="ipaddr" name="ip"><br>
                      <input type="submit" value="提交">
                  </form>
              </body>
          </html>
          

          后端代碼:

          from flask import Flask, request
          
          webapp = Flask(__name__)
          
          @webapp.route('/ttropsstack', methods=["POST"])
          def ttropsstack():
              args = request.args
              print 'ip addr is: %s' % args.get('ip')
              return 'ok'
          
          if __name__ == '__main__':
          
              webapp.run(host="0.0.0.0", port=8088, debug=True)
          

          當前端輸入數(shù)據(jù)后,提交表單時,直接告訴你這是不允許的方法

          在這個例子中,是因為前端的表單了指定了method為get請求,而后端接收數(shù)據(jù)的method規(guī)定了需要post請求,故所以出現(xiàn)這個問題。

          下面我們改造一下后端代碼:

          # coding: utf8
          from flask import Flask, request
          
          webapp = Flask(__name__)
          
          @webapp.route('/ttropsstack', methods=['GET','POST'])
          def ttropsstack():
              if request.method == 'POST':
                  print request.get_data(as_text=True)
                  return 'ok'
              else:
                  return '提交數(shù)據(jù)需要post請求'
          
          if __name__ == '__main__':
          
              webapp.run(host="0.0.0.0", port=8088, debug=True)
          

          前端表單中的method還是保持get請求,再次提交,后端的返回如下:

          看到了嗎?后端判斷前端過來的請求是get還是post,很顯然,前端過來的請求是get,并且返回了非常友好的提示。

          接下來我們繼續(xù)改造一下前端的代碼,將請求修改為post,代碼如下:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <h3>主機信息</h3>
                  <form action="http://192.168.11.10:8088/ttropsstack" target="_blank" method="post">
                      <label for="ipaddr">IP地址</label>
                      <input type="text" id="ipaddr" name="ip"><br>
                      <input type="submit" value="提交">
                  </form>
              </body>
          </html>
          

          后端代碼也稍微改造一下,改變接收前端數(shù)據(jù)的方法

          # coding: utf8
          from flask import Flask, request
          
          webapp = Flask(__name__)
          
          @webapp.route('/ttropsstack', methods=['GET','POST'])
          def ttropsstack():
              if request.method == 'POST':
                  a = request.form
                  print a.get('ip')
                  print type(a)
                  return 'ok'
              else:
                  return '提交數(shù)據(jù)需要post請求'
          
          if __name__ == '__main__':
          
              webapp.run(host="0.0.0.0", port=8088, debug=True)
          

          輸入IP地址,并點擊提交

          提交后,后端給前端返回了ok

          接下來看下后端,后端啥也沒做,就獲取到表單的數(shù)據(jù),然后打印了數(shù)據(jù),并且打印了下數(shù)據(jù)類型

          好了,關(guān)于前端的action屬性和Method屬性就講到這里了。為了講解action和method,還結(jié)合了后端的一丟丟知識,前端和后端的知識點以后都會慢慢講到哈!

          HTML表單常用元素

          1. 下拉列表

          先來個前端代碼:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <form action="http://192.168.11.10:8088/ttropsstack" target="_blank" method="post">
                      <label for="opslist">運維開發(fā)應(yīng)掌握的技能:</label>
                      <select id="opslist" name="opslist">
                          <option value="python">Python語言</option>
                          <option value="go">Go語言</option>
                          <option value="shell">Shell語言</option>
                          <option value="database">數(shù)據(jù)庫</option>
                          <option value="frontend">前端</option>
                          <option value="linux">Linux</option>
                          <option value="network">網(wǎng)絡(luò)</option>
                          <option value="storage">存儲</option>
                      </select>
                      <input type="submit">
                  </form>
              </body>
          </html>
          

          后端代碼:

          # coding: utf8
          from flask import Flask, request
          
          webapp = Flask(__name__)
          
          @webapp.route('/ttropsstack', methods=['GET','POST'])
          def ttropsstack():
              if request.method == 'POST':
                  a = request.form
                  print a.get('opslist')
                  return 'ok'
              else:
                  return '提交數(shù)據(jù)需要post請求'
          
          if __name__ == '__main__':
          
              webapp.run(host="0.0.0.0", port=8088, debug=True)
          

          在下拉框中選擇“Go語言”,并提交

          后端啥也沒干,就只做了打印

          2. 允許多選

          前端代碼:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <form action="http://192.168.11.10:8088/ttropsstack" target="_blank" method="post">
                      <label for="opslist">運維開發(fā)應(yīng)掌握的技能:</label>
                      <select id="opslist" name="opslist" size="6" multiple>
                          <option value="python">Python語言</option>
                          <option value="go">Go語言</option>
                          <option value="shell">Shell語言</option>
                          <option value="database">數(shù)據(jù)庫</option>
                          <option value="frontend">前端</option>
                          <option value="linux">Linux</option>
                          <option value="network">網(wǎng)絡(luò)</option>
                          <option value="storage">存儲</option>
                      </select>
                      <input type="submit">
                  </form>
              </body>
          </html>
          

          上述前端代碼中,是使用multiple屬性來實現(xiàn)選擇多個值。

          后端代碼的打印方式稍微做了些許調(diào)整:

          # coding: utf8
          from flask import Flask, request
          
          webapp = Flask(__name__)
          
          @webapp.route('/ttropsstack', methods=['GET','POST'])
          def ttropsstack():
              if request.method == 'POST':
                  data = request.get_data()
                  print data
                  return 'ok'
              else:
                  return '提交數(shù)據(jù)需要post請求'
          
          if __name__ == '__main__':
          
              webapp.run(host="0.0.0.0", port=8088, debug=True)
          

          按住ctrl或者shift鍵可進行多選

          后端打印的效果圖下圖:

          寫在最后

          關(guān)于表單基礎(chǔ)知識點的講解就這么愉快的結(jié)束了,關(guān)于更多表單的元素、輸入屬性、輸入類型可自行查閱和實戰(zhàn),筆者因時間有限就不一一演示。感謝您的閱讀,望多多關(guān)注我們、點贊、轉(zhuǎn)發(fā)!

          本文轉(zhuǎn)載于(喜歡的盆友關(guān)注我們):https://mp.weixin.qq.com/s/L-Msv39JrF7AzRx4K1OLjA


          主站蜘蛛池模板: 国产成人高清亚洲一区久久| 亚洲国产精品一区第二页| 亚洲免费视频一区二区三区 | 亚洲日韩一区精品射精| 久久综合精品国产一区二区三区| 亚洲av无码一区二区三区观看| 精品久久久久一区二区三区 | 国产电影一区二区| 亚洲综合av永久无码精品一区二区| 国产SUV精品一区二区88| 精品无码日韩一区二区三区不卡| 九九久久99综合一区二区| 国产高清在线精品一区二区| 色视频综合无码一区二区三区| 国产成人精品一区二区A片带套| 无码日韩人妻av一区免费| 无码国产精品一区二区免费式直播 | 国产一区二区精品尤物| 亚洲av片一区二区三区| 精品无码一区二区三区水蜜桃| 国产伦精品一区三区视频| 国产精品亚洲专区一区 | 亚洲av无码一区二区三区网站| 国产丝袜美女一区二区三区| 日本道免费精品一区二区| 国产在线精品一区二区在线观看 | 色一情一乱一区二区三区啪啪高| 国产手机精品一区二区| 久久一区二区三区精华液使用方法 | 国产午夜一区二区在线观看| 国产精品无码一区二区在线观| 国产麻豆剧果冻传媒一区 | 国产精品免费视频一区| 秋霞鲁丝片一区二区三区| 国产一区二区三区电影| 久久成人国产精品一区二区| 99精品国产高清一区二区三区| 少妇激情一区二区三区视频 | 国产精品特级毛片一区二区三区| 久久se精品一区二区| 亚洲av无一区二区三区|