整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          HTML+AJAX實現上傳大文件實例解析

          JAX上傳的用戶體驗更好,HTML上傳用戶使用更方便一點,直接在網頁里面就能夠操作了。示例在下面提供了,是完整的源代碼,有教程,有視頻教程,基本上使用非常簡單,開發(fā)也非常簡單,有技術支持,

          網上搜了一下,基本上講這塊的文章還是很多,但是就是一個字亂,講的很混亂。也沒有提供完整的前后端示例。

          用戶上傳的文件比較大,有20G左右,直接用HTML傳的話容易失敗,服務器也容易出錯,需要分片,分塊,分割上傳。也就是將一個大的文件分成若干個小文件塊來上傳,另外就是需要實現秒傳功能和防重復功能,秒傳就是用戶如果上傳過這個文件,那么直接在數據庫中查找記錄就行了,不用再上傳一次,節(jié)省時間,實現的思路是對文件做MD5計算,將MD5值保存到數據庫,算法可以用MD5,或者CRC,或者SHA1,這個隨便哪個算法都行。

          分片還需要支持斷點續(xù)傳,現在HTML5雖然提供了信息記錄功能,但是只支持到了會話級,也就是用戶不能關閉瀏覽器,也不能清空緩存。但是有的政府單位上傳大文件,傳了一半下班了,明天繼續(xù)傳,電腦一關結果進度信息就丟失了,這個是他們的一個痛點。

          切片的話還有一點就是在服務器上合并,一個文件的所有分片數據上傳完后需要在服務器端進行合并操作。


          1.下載示例

          https://gitee.com/xproer/up6-vue-cli



          將up6組件復制到項目中

          示例中已經包含此目錄



          1.引入up6組件



          2.配置接口地址

          接口地址分別對應:文件初始化,文件數據上傳,文件進度,文件上傳完畢,文件刪除,文件夾初始化,文件夾刪除,文件列表

          參考:http://www.ncmem.com/doc/view.aspx?id=e1f49f3e1d4742e19135e00bd41fa3de



          3.處理事件



          啟動測試



          啟動成功



          效果



          數據庫

          :SSO體系結構

          SSO

          ? SSO英文全稱Single Sign On,單點登錄。SSO是在多個應用系統中,用戶只需要登錄一次就可以訪問所有相互信任的應用系統。它包括可以將這次主要的登錄映射到其他應用中用于同一個用戶的登錄的機制。它是目前比較流行的企業(yè)業(yè)務整合的解決方案之一。

          體系結構

          ? 當用戶第一次訪問應用系統1的時候,因為還沒有登錄,會被引導到認證系統中進行登錄;根據用戶提供的登錄信息,認證系統進行身份校驗,如果通過校驗,應該返回給用戶一個認證的憑據--token;用戶再訪問別的應用的時候就會將這個token帶上,作為自己認證的憑據,應用系統接受到請求之后會把token送到認證系統進行校驗,檢查token的合法性。如果通過校驗,用戶就可以在不用再次登錄的情況下訪問應用系統2和應用系統3了 。



          Token(令牌)

          token的意思是“令牌”,是服務端生成的一串字符串,作為客戶端進行請求的一個標識。

          當用戶第一次登錄后,服務器生成一個token并將此token返回給客戶端,客戶端收到token后把它存儲起來,可以放在cookie或者Local Storage(本地存儲)里。 以后客戶端只需帶上這個token前來請求數據即可,無需再次帶上用戶名和密碼。

          簡單token的組成;uid(用戶唯一的身份標識)、time(當前時間的時間戳)、sign(簽名,token的前幾位以哈希算法壓縮成的一定長度的十六進制字符串。為防止token泄露)。

          設計token的值可以有以下方式

          1. 用設備mac地址作為token
          2. 用sessionid作為token

          同域SSO原理分析

          實際上,HTTP協議是無狀態(tài)的,單個系統的會話由服務端Session進行維持,Session保持會話的原理是通過Cookie把sessionId寫入瀏覽器,每次訪問都會自動攜帶全部Cookie,在服務端讀取其中的sessionId進行驗證實現會話保持。同域下單點登錄其實就是手寫token代替sessionId進行會話認證。

          token的生成

          服務端生成token后,將token與user對象存儲在Map結構中,token為Key,user對象為value,response.addCookie()生成新的Cookie,名為token,值為token的值。

          token過期移除

          將服務端的token從Map中移除,再刪除瀏覽器端的名為token的Cookie。

          認證流程



          跨域SSO原理分析

          當有多個系統時,認證機制的流程如下:

          1. 提供用戶登錄界面,供用戶進行身份認證
          2. 用戶驗證通過后,生成新token
          3. 將token<->user 對存入全局MAP中供校驗
          4. 將token寫入所有域的Cookie中
          5. 頁面重定向回原始請求URL

          分析

          當系統有多個并且在不同域(domain)時,Cookie只會作用在當前域下。

          將token寫入所有域的Cookie中才是解決跨域SSO的核心。



          二:Cookie增刪改查

          如何讀取Cookie?

          通過Servlet中的request對象可以讀取到Cookie數組,然后foreach遍歷讀取,一般只是獲取到nam和value,其他信息寫入到瀏覽器后,瀏覽器不主動再發(fā)回來,讀取并無意義。

                  Cookie[] cookies = request.getCookies();
                  if (cookies != null) {
                      for (Cookie cookie : cookies) {
                          System.out.println(
                                  cookie.getName() +
                                  cookie.getValue() +
                                  cookie.getMaxAge() +
                                  cookie.getPath() +
                                  cookie.getDomain() +
                                  cookie.getSecure() +
                                  cookie.isHttpOnly()//客戶端js是否可以獲取
                          );
                      }
                  }
          復制代碼

          如何寫入Cookie帶瀏覽器?

          新建Cookie對象設置一系列屬性,然后添加到response中去。需要注意的是,當設置path為“/”時,表示所有路徑都會被該Cookie作用到,如果設置為/path1那么由/path2發(fā)起請求就不會攜帶該Cookie。默認不設置只作用在當前路徑下。

                  Cookie cookie = new Cookie("myCookieName","myCookieValue");
                  cookie.setHttpOnly(false);//Javascript不能處理
                  //一個正值表示cookie將在經過許多秒之后過期。注意,值是cookie過期的最大時間,而不是cookie當前的時間。
                  //負值表示cookie沒有持久存儲,在Web瀏覽器退出時將被刪除。零值會導致刪除cookie。
                  cookie.setMaxAge(-1000);
                  cookie.setSecure(false);//如果為true,僅支持HTTPS協議
                  //cookie對指定目錄中的所有頁面以及該目錄子目錄中的所有頁面都可見。
                  cookie.setPath("/");
                  //cookie.setDomain("www.a.com");//默認情況下,cookie只返回給發(fā)送cookie的服務器。
                  response.addCookie(cookie);
          復制代碼

          修改Cookie

          修改更新Cookie時,除了要保證Cookie的name是相同的,也要保證Cookie的一系列屬性是相同的,否則瀏覽器會生成新的Cookie。

          刪除Cookie

          只需要設置Cookie的MaxAge為負值,意味著是過去的Cookie,瀏覽器就會清除。

          三:跨域讀寫Cookie

          1.利用HTML的script標簽跨域寫Cookie

          比如當前域是www.a.com,下面的script標簽是跨域寫cookie的核心,通過此標簽實現了向www.b.com域寫入cookie:

          <script type="text/javascript" src="http://www.b.com/setCookie?cname=token&cval=123456"></script>
          復制代碼

          P3P協議

          ? P3P是一種被稱為個人隱私安全平臺項目(the Platform for Privacy Preferences)的標準,能夠保護在線隱私權,使Internet沖浪者可以選擇在瀏覽網頁時,是否被第三方收集并利用自己的個人信息。如果一個站點不遵守P3P標準的話,那么有關它的Cookies將被自動拒絕,并且P3P還能夠自動識破多種Cookies的嵌入方式。p3p是由全球資訊聯盟網所開發(fā)的。

          舉個例子:

          ? 我們在訪問A網站時,理論上說,我們只能把Cookie信息保存到A站域名下,而不能寫入到B網站下。如果想要跨域讀寫Cookie,只是通過script標簽變相訪問B網站在一些瀏覽器是行不通的,此時B網站的服務器應該告訴瀏覽器允許A網站寫入Cookie,否則瀏覽器將會拒絕執(zhí)行,這就是P3P協議。

          服務端如何告訴瀏覽器?

          ? P3P提供了一種簡單的方式 ,來加載用戶隱私策略,只要在http響應的頭信息中增加 response.setHeader("P3P","CP=NON DSP COR CURa ADMa DEVa TAIa PSAa PSDa IVAa IVDa CONa HISa TELa OTPa OUR UNRa IND UNI COM NAV INT DEM CNT PRE LOC);而無需指定隱私策略文件也可以達到指定隱私策略的目的。 CP=后面的字符串分別代表不同的策略信息。

          總結

          因為P3P協議所以不能保證所有瀏覽器都能通過script標簽方式跨域寫Cookie,有的瀏覽器本身就是拒絕跨域的。

          顯然這種方式是不能保證跨域寫cookie的成功性。

          2.通過URL參數實現跨域信息傳遞

          我們要在A域實現寫入token到B域,需要在A域設計一個servlet接收請求,代碼:

          @WebServlet(name = "tg")
          public class Servlet extends HttpServlet {
              protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
                  //獲取請求的目標域
                  String from = request.getParameter("from");
                  //生成token,
                  String token = "123456";
                  //重定向到目標域
                  response.sendRedirect(from + "?cname=token&cval=" + token);
              }
              ...
           }
          復制代碼

          由a域發(fā)起請求,請求地址:http://www.a.com/tg?from=http://www.b.com/set_cookie, 請求后該Servlet會獲取from參數的值并生成token最后讓客戶端重定向到http://www.b.com/set_cookie?cname=token&cval=123456,然后B域的Servlet("set_cookie")獲取Url參數寫入Cookie到客戶端,代碼:

                  //將要寫入的cookie項,調用者通過參數傳遞
                  String cookieName = request.getParameter("cname");
                  String cookieValue = request.getParameter("cval");
          
                  //生成cookie
                  Cookie cookie = new Cookie(cookieName,cookieValue);
                  cookie.setPath("/");
                  //一般可以將domain設置到頂級域
                  //cookie.setDomain("www.b.com");
                  response.addCookie(cookie);
          復制代碼

          這時候再查看B域下的Cookie就可以發(fā)現(token=123456)已經被寫入到瀏覽器。

          3.讀取其它域的Cookie

          利用script標簽

          利用script標簽執(zhí)行另一個域實現的讀取cookie方法,script標簽返回結果將是變量定義形式的JS代碼,每一個變量表示一個cookie項,這些代碼加載后,此頁面后續(xù)JS代碼可以直接在script腳本中讀取已定義的變量值,即各cookie值。

          <script type="text/javascript" src="http://www.b.com/reaf_cookies"></script>
          復制代碼

          HTML頁面讀取

          <script>
          alert(token);
          </script>
          復制代碼

          B域的url為/read_cookies的Servlet是如何實現的?

          如圖,首先我們先在request中獲取cookie數組,然后for循環(huán)遍歷拼接為類似var token='test123';的字符串。最重要的是設置ContentType為application/javascript,代碼如下:

              protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                  Cookie[] cookies = request.getCookies();
                  StringBuilder stringBuilder = new StringBuilder();
                  //一定要設置響應類型,否則可能導致IE不解析js直接進行下載操作
                  response.setContentType("application/javascript");
          
                  if (cookies != null) {
                      for (Cookie cookie : cookies) {
                          //結果類似于這樣 var token='123456';
                          stringBuilder.append("var ")
                                  .append(cookie.getName())
                                  .append("=")
                                  .append("'")
                                  .append(cookie.getValue())
                                  .append("'")
                                  .append(";");
                      }
                      response.getWriter().append(stringBuilder.toString());
                  }
               }
          復制代碼

          四:跨域Ajax請求

          1.Jsonp的方式

          跨域Ajax請求在瀏覽器階段就會被阻止,我們可以通過script標簽返回想要的json數據。如圖:

           <script type="text/javascript" src="http://www.b.com/user_info_2"></script>
          復制代碼

          后臺Servlet代碼

                  //要正確設置響應類型,避免IE出現下載
                  response.setContentType("application/javascript");
          
                  String userInfo = "{\"id\":1,\"name\":\"zhangsan\"}";
          
                  //返回拼接的javascript語句字符串,語句本身執(zhí)行一個調用函數的操作
                  String ret = "showResult("+userInfo+")";
          復制代碼

          在Servlet中設置返回類型為javascript,并正常獲取json格式的數據,最關鍵的是在最后拼接為js語句字符串,語句本身就是執(zhí)行一個調用函數的操作:

          showResult({"id":1,"name":"zhangsan"})
          復制代碼

          而showResult(ret)回調函數自然需要我們在之前就定義好:

              <script>
                  function showResult(ret){
                      console.log(ret)
                  }
              </script>
          復制代碼

          優(yōu)化

          這種方式,前端的回調函數和后端耦合度較高。前端可以在調用后端方法時帶上回調函數名(?callback=xxxxx),后端優(yōu)化后的代碼:

                  //通過參數傳遞回調函數名,一定程度降低了前后端代碼的耦合度
                  String callback = request.getParameter("callback");
          
                  //返回拼接的javascript語句字符串,語句本身執(zhí)行一個調用函數的操作
                  String ret = callback+"("+userInfo+")";
          復制代碼

          再優(yōu)化

          HTML頁面加載到我們定義的script標簽時就會執(zhí)行我們的回調方法,更多時候我們想要控制回調方法的執(zhí)行時機。這個問題可以通過前端動態(tài)生成節(jié)點來解決,當我們執(zhí)行完之后再移除節(jié)點即可:

              <script>
                  var script = document.createElement("script");
                  script.src = "http://www.b.com/user_info_2?callback=showResult";
                  document.body.appendChild(script);
          
                  script.onload = function () {
                      document.body.removeChild(script);
                  }
              </script>
          復制代碼

          JQuery

          我們可以把這些封裝到一個方法里,隨時調用。這里可以使用Jquery封裝好的API。

                          $.ajax({
                              url: "http://localhost:9090/query",
                              type: "GET",
                              dataType: "jsonp",  //指定服務器返回的數據類型
                              jsonpCallback: "showData",  //指定回調函數名稱
                              success: function (data) {
                                  console.info("調用success");
                              }
                          });
                          function showData(data){
                              var result = JSON.stringify(data);
                          }
          復制代碼

          2.CORS簡介

          出于安全原因,瀏覽器限制從腳本內發(fā)起的跨源HTTP請求。 例如,XMLHttpRequest和Fetch API遵循同源策略。 這意味著使用這些API的Web應用程序只能從加載應用程序的同一個域請求HTTP資源,除非使用CORS頭文件。

          跨域資源共享( CORS)機制允許 Web 應用服務器進行跨域訪問控制,從而使跨域數據傳輸得以安全進行。瀏覽器支持在 API 容器中(例如 XMLHttpRequest或 Fetch)使用 CORS,以降低跨域 HTTP 請求所帶來的風險。

          GET跨域請求原理

          當客戶端瀏覽器發(fā)起一個跨域的HTTP請求,瀏覽器經過請求響應,如果沒有看到Access-Control-Allow-Origin的header頭部,會認為你的請求是不合法的。換句話說,我們只要在被請求的服務器上設置這個頭部,瀏覽器就會允許我們進行請求。

          解決方法

          對于簡單的請求,我們直接在服務端 設置就可以了。如圖,只要請求的地址是www.a.com就會被瀏覽器允許跨域。如果想要允許對于多個來源可以用,號進行隔開;如果想要允許所有來源,設置為*就可以,不過建議不要使用,這樣會造成安全隱患。

              protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                  //簡單請求,直接設置Access-Control-Allow-Origin就可以了
                  response.setHeader("Access-Control-Allow-Origin","*");
                  //要正確設置響應類型,避免IE出現下載
                  response.setContentType("application/json");
          
                  response.getWriter().write("{\"id\":1,\"name\":\"zhangsan\"}");
              }
          復制代碼

          對于復雜的請求,比如POST,或者加入了自定義header頭部,上面的方法就不適用了。下面繼續(xù)看。

          CORS流程

          請求發(fā)起時,瀏覽器先判斷當前是否是跨域的AJAX;

          如果是,判斷是否是普通類型請求(GET類型,無自定義頭數據);

          普通請求,直接發(fā)起GET到服務端,在響應頭中尋找 Access-Contro-Alow- Origin,如果有且允許,處理響應結果;

          不是普通請求(非GET類型,或有自定義頭), 先 PreFlight(即發(fā)起一個 method= OPTIONS)的請求,

          要求返回 Access-Control-Allow- Methods和 Access-Control-Allow- Headers, 內容體為空

          PreFlight正確執(zhí)行后, 再發(fā)起GET請求, 獲得響應結果, 并處理結果.

          實現

          歸根到我們的代碼中的實現,只需要在servlet中定義options請求的處理方法即可。如圖

              protected void doOptions(HttpServletRequest req, HttpServletResponse response) {
                  response.setHeader("Access-Control-Allow-Origin","*");
                  response.setHeader("Access-Control-Allow-Methods","GET,POST,OPTIONS,DELETE");
                  response.setHeader("Access-Control-Allow-Headers","reqid,xxx");
              }
          復制代碼

          注意:Access-Control-Allow-Origin是必需的。

          3.兩種跨域AJax請求對比

          兼容性

          Jsonp對所有瀏覽器兼容,CORS對現代瀏覽器兼容(IE8之后)。

          請求方式

          Jsonp只支持GET方式,CORS支持GET,POST等。

          調用方式

          Jsonp需要服務端封裝返回信息,CORS更像原生AJax一樣使用。


          作者:風平浪靜如碼
          鏈接:https://juejin.im/post/5e81e82551882573a1377a08

          JAX準備知識:JSON

          什么是 JSON ?

        1. JSON 指的是 JavaScript 對象表示法(JavaScript Object Notation)
        2. JSON 是輕量級的文本數據交換格式
        3. JSON 獨立于語言 *
        4. JSON 具有自我描述性,更易理解
        5. * JSON 使用 JavaScript 語法來描述數據對象,但是 JSON 仍然獨立于語言和平臺。JSON 解析器和 JSON 庫支持許多不同的編程語言。


          合格的json對象:

          ["one", "two", "three"]
          { "one": 1, "two": 2, "three": 3 }
          {"names": ["張三", "李四"] }
          [ { "name": "張三"}, {"name": "李四"} ] 

          不合格的json對象:

          { name: "張三", 'age': 32 }  // 屬性名必須使用雙引號
          [32, 64, 128, 0xFFF] // 不能使用十六進制值
          { "name": "張三", "age": undefined }  // 不能使用undefined
          { "name": "張三",
            "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
            "getName":  function() {return this.name;}  // 不能使用函數和日期對象
          }

          stringify與parse方法

          JavaScript中關于JSON對象和字符串轉換的兩個方法:

          JSON.parse(): 用于將一個 JSON 字符串轉換為 JavaScript 對象 

          JSON.parse('{"name":"run1"}');
          JSON.parse('{name:"run1"}') ;   // 錯誤
          JSON.parse('[18,undefined]') ;   // 錯誤

          JSON.stringify(): 用于將 JavaScript 值轉換為 JSON 字符串。 

          JSON.stringify({"name":"run1"})

          和XML的比較

          JSON 格式于2001年由 Douglas Crockford 提出,目的就是取代繁瑣笨重的 XML 格式。

          JSON 格式有兩個顯著的優(yōu)點:書寫簡單,一目了然;符合 JavaScript 原生語法,可以由解釋引擎直接處理,不用另外添加解析代碼。所以,JSON迅速被接受,已經成為各大網站交換數據的標準格式,并被寫入ECMAScript 5,成為標準的一部分。

          XML和JSON都使用結構化方法來標記數據,下面來做一個簡單的比較。

          用XML表示中國部分省市數據如下:

          <?xml version="1.0" encoding="utf-8"?>
          <country>
              <name>中國</name>
              <province>
                  <name>黑龍江</name>
                  <cities>
                      <city>哈爾濱</city>
                      <city>大慶</city>
                  </cities>
              </province>
              <province>
                  <name>廣東</name>
                  <cities>
                      <city>廣州</city>
                      <city>深圳</city>
                      <city>珠海</city>
                  </cities>
              </province>
              <province>
                  <name>臺灣</name>
                  <cities>
                      <city>臺北</city>
                      <city>高雄</city>
                  </cities>
              </province>
              <province>
                  <name>新疆</name>
                  <cities>
                      <city>烏魯木齊</city>
                  </cities>
              </province>
          </country>

          用JSON表示如下

          {
              "name": "中國",
              "province": [{
                  "name": "黑龍江",
                  "cities": {
                      "city": ["哈爾濱", "大慶"]
                  }
              }, {
                  "name": "廣東",
                  "cities": {
                      "city": ["廣州", "深圳", "珠海"]
                  }
              }, {
                  "name": "臺灣",
                  "cities": {
                      "city": ["臺北", "高雄"]
                  }
              }, {
                  "name": "新疆",
                  "cities": {
                      "city": ["烏魯木齊"]
                  }
              }]
          }

          由上面的兩段代碼可以看出,JSON 簡單的語法格式和清晰的層次結構明顯要比 XML 容易閱讀,并且在數據交換方面,由于 JSON 所使用的字符要比 XML 少得多,可以大大得節(jié)約傳輸數據所占用的帶寬。

          AJAX簡介

          AJAX(Asynchronous Javascript And XML)翻譯成中文就是“異步Javascript和XML”。即使用Javascript語言與服務器進行異步交互,傳輸的數據為XML(當然,傳輸的數據不只是XML)。

          • 同步交互:客戶端發(fā)出一個請求后,需要等待服務器響應結束后,才能發(fā)出第二個請求;
          • 異步交互:客戶端發(fā)出一個請求后,無需等待服務器響應結束,就可以發(fā)出第二個請求。

          AJAX除了異步的特點外,還有一個就是:瀏覽器頁面局部刷新;(這一特點給用戶的感受是在不知不覺中完成請求和響應過程)

          示例:

          頁面輸入兩個整數,通過AJAX傳輸到后端計算出結果并返回。

          HTML部分代碼

          <!DOCTYPE html>
          <html lang="en">
          <head>
            <meta charset="UTF-8">
            <meta http-equiv="x-ua-compatible" content="IE=edge">
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <title>AJAX局部刷新實例</title>
          </head>
          <body>
          
          <input type="text" id="i1">+
          <input type="text" id="i2">=
          <input type="text" id="i3">
          <input type="button" value="AJAX提交" id="b1">
          
          <script src="/static/jquery-3.2.1.min.js"></script>
          <script>
            $("#b1").on("click", function () {
              $.ajax({
                url:"/ajax_add/",
                type:"GET",
                data:{"i1":$("#i1").val(),"i2":$("#i2").val()},
                success:function (data) {
                  $("#i3").val(data);
                }
              })
            })
          </script>
          </body>
          </html>

          views.py

          def ajax_demo1(request):
              return render(request, "ajax_demo1.html")
          
          
          def ajax_add(request):
              i1 = int(request.GET.get("i1"))
              i2 = int(request.GET.get("i2"))
              ret = i1 + i2
              return JsonResponse(ret, safe=False)

          urls.py

          urlpatterns = [
              ...
              url(r'^ajax_add/', views.ajax_add),
              url(r'^ajax_demo1/', views.ajax_demo1),
              ...   
          ]

          AJAX語法

          $.ajax({
              url:"",  // 控制往哪里提交
              type:"POST",  // 請求的方法
              data:{},  // 請求的參數
              success:function(arg){
                  // 收到響應之后要做的事
              }
          })

          AJAX常見應用情景

          搜索引擎根據用戶輸入的關鍵字,自動提示檢索關鍵字。

          還有一個很重要的應用場景就是注冊時候的用戶名的查重。

          其實這里就使用了AJAX技術!當文件框發(fā)生了輸入變化時,使用AJAX技術向服務器發(fā)送一個請求,然后服務器會把查詢到的結果響應給瀏覽器,最后再把后端返回的結果展示出來。

          • 整個過程中頁面沒有刷新,只是刷新頁面中的局部位置而已!
          • 當請求發(fā)出后,瀏覽器還可以進行其他操作,無需等待服務器的響應!


          當輸入用戶名后,把光標移動到其他表單項上時,瀏覽器會使用AJAX技術向服務器發(fā)出請求,服務器會查詢名為lemontree7777777的用戶是否存在,最終服務器返回true表示名為lemontree7777777的用戶已經存在了,瀏覽器在得到結果后顯示“用戶名已被注冊!”。

          • 整個過程中頁面沒有刷新,只是局部刷新了;
          • 在請求發(fā)出后,瀏覽器不用等待服務器響應結果就可以進行其他操作;

          AJAX的優(yōu)缺點

          優(yōu)點

          • AJAX使用JavaScript技術向服務器發(fā)送異步請求;
          • AJAX請求無須刷新整個頁面;
          • 因為服務器響應內容不再是整個頁面,而是頁面中的部分內容,所以AJAX性能高;

          jQuery實現的AJAX

          最基本的jQuery發(fā)送AJAX請求示例

          <!DOCTYPE html>
          <html lang="zh-CN">
          <head>
            <meta charset="UTF-8">
            <meta http-equiv="x-ua-compatible" content="IE=edge">
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <title>ajax test</title>
            <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
          </head>
          <body>
          <button id="ajaxTest">AJAX 測試</button>
          <script>
            $("#ajaxTest").click(function () {
              $.ajax({
                url: "/ajax_test/",
                type: "POST",
                data: {username: "Q1mi", password: 123456},
                success: function (data) {
                  alert(data)
                }
              })
            })
          </script>
          </body>
          </html>

          views.py

          def ajax_test(request):
              user_name = request.POST.get("username")
              password = request.POST.get("password")
              print(user_name, password)
              return HttpResponse("OK")

          $.ajax參數

          data參數中的鍵值對,如果值值不為字符串,需要將其轉換成字符串類型。

          $("#b1").on("click", function () {
              $.ajax({
                url:"/ajax_add/",
                type:"GET",
                data:{"i1":$("#i1").val(),"i2":$("#i2").val(),"hehe": JSON.stringify([1, 2, 3])},
                success:function (data) {
                  $("#i3").val(data);
                }
              })
            })

          AJAX請求如何設置csrf_token

          方式1

          通過獲取隱藏的input標簽中的csrfmiddlewaretoken值,放置在data中發(fā)送。

          $.ajax({
            url: "/cookie_ajax/",
            type: "POST",
            data: {
              "username": "rum2",
              "password": 123456,
              "csrfmiddlewaretoken": $("[name = 'csrfmiddlewaretoken']").val()  // 使用JQuery取出csrfmiddlewaretoken的值,拼接到data中
            },
            success: function (data) {
              console.log(data);
            }
          })

          方式2

          通過獲取返回的cookie中的字符串 放置在請求頭中發(fā)送。

          注意:需要引入一個jquery.cookie.js插件。

          $.ajax({
            url: "/cookie_ajax/",
            type: "POST",
            headers: {"X-CSRFToken": $.cookie('csrftoken')},  // 從Cookie取csrf_token,并設置ajax請求頭
            data: {"username": "rum", "password": 123456},
            success: function (data) {
              console.log(data);
            }
          })

          或者用自己寫一個getCookie方法:

          function getCookie(name) {
              var cookieValue = null;
              if (document.cookie && document.cookie !== '') {
                  var cookies = document.cookie.split(';');
                  for (var i = 0; i < cookies.length; i++) {
                      var cookie = jQuery.trim(cookies[i]);
                      // Does this cookie string begin with the name we want?
                      if (cookie.substring(0, name.length + 1) === (name + '=')) {
                          cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                          break;
                      }
                  }
              }
              return cookieValue;
          }
          var csrftoken = getCookie('csrftoken');

          每一次都這么寫太麻煩了,可以使用$.ajaxSetup()方法為ajax請求統一設置。

          function csrfSafeMethod(method) {
            // these HTTP methods do not require CSRF protection
            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
          }
          
          $.ajaxSetup({
            beforeSend: function (xhr, settings) {
              if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
              }
            }
          });

          序列化

          Django內置的serializers

          def books_json(request):
              book_list = models.Book.objects.all()[0:10]
              from django.core import serializers
              ret = serializers.serialize("json", book_list)
              return HttpResponse(ret)

          我們的數據中經常有日期時間,也就是datetime對象,而json.dumps是無法處理這樣在類型的,那就需要通過自定義處理器來做擴展,如下:

          class JsonCustomEncoder(json.JSONEncoder):
              """
              自定義一個支持序列化時間格式的類
              """
          
              def default(self, o):
                  if isinstance(o, datetime):
                      return o.strftime("%Y-%m-%d %H:%M:%S")
                  elif isinstance(o, date):
                      return o.strftime("%Y-%m-%d")
                  else:
                      return json.JSONEncoder.default(self, o)
          
          
          def books_json(request):
              book_list = models.Book.objects.all().values_list("title", "publish_date")
              ret = json.dumps(list(book_list), cls=JsonCustomEncoder)
              return HttpResponse(ret)

          Bootstrap-sweetalert

          https://github.com/lipis/bootstrap-sweetalert
          $(".btn-danger").on("click", function () {
            swal({
              title: "你確定要刪除嗎?",
              text: "刪除可就找不回來了哦!",
              type: "warning",
              showCancelButton: true,
              confirmButtonClass: "btn-danger",
              confirmButtonText: "刪除",
              cancelButtonText: "取消",
              closeOnConfirm: false
              },
              function () {
                var deleteId = $(this).parent().parent().attr("data_id");
                $.ajax({
                  url: "/delete_book/",
                  type: "post",
                  data: {"id": deleteId},
                  success: function (data) {
                    if (data.status === 1) {
                      swal("刪除成功!", "你可以準備跑路了!", "success");
                    } else {
                      swal("刪除失敗", "你可以再嘗試一下!", "error")
                    }
                  }
                })
              });
          })

          #科技##軟件開發(fā)##python#


          主站蜘蛛池模板: 青娱乐国产官网极品一区| 国产一区二区三区精品久久呦| 国产婷婷色一区二区三区深爱网| 国产一区二区视频在线播放| 色狠狠一区二区三区香蕉蜜桃 | 狠狠做深爱婷婷久久综合一区| 无码欧精品亚洲日韩一区| 人妻无码一区二区三区AV| 国产乱码精品一区二区三区四川人 | 国产成人综合亚洲一区| 亚洲AV无码一区二区三区系列| 亚洲AV色香蕉一区二区| 国产精品视频一区二区三区无码| 亚洲蜜芽在线精品一区| 亚洲国产系列一区二区三区| 国产探花在线精品一区二区| 精品少妇ay一区二区三区 | 鲁丝片一区二区三区免费| 亚洲Av无码一区二区二三区| 免费无码一区二区| 日韩中文字幕精品免费一区| 红桃AV一区二区三区在线无码AV| 久久青青草原一区二区| 精品欧洲AV无码一区二区男男| 一区二区三区在线免费| 一区二区精品在线观看| 国产福利无码一区在线| 人妻免费一区二区三区最新| 无码人妻精品一区二区蜜桃网站 | 亚洲AV成人精品日韩一区18p| 国产一区高清视频| 久久青草精品一区二区三区| 午夜性色一区二区三区不卡视频| 不卡一区二区在线| 日韩精品无码人妻一区二区三区| 亚洲av无码一区二区三区观看| 成人免费av一区二区三区| 日韩视频在线一区| 国产大秀视频一区二区三区| 国产精品伦子一区二区三区 | 亚洲丰满熟女一区二区v|