Django(十九)Ajax全套

參考博客:http://www.cnblogs.com/wupeiqi/articles/5703697.htmljavascript

 

提交:
    - Form
    - Ajax

1、Ajax,偷偷向後臺發請求
    - XMLHttpRequest
        - 手動使用
        - jQuery
    - 「僞」Ajax
        - iframe標籤
        - form表單
    
2、Ajax上傳文件
    - jQuery
    - 原生
    以上兩種方式可利用formData對象,來封裝用戶提交的數據
    
    - Iframe+Form
    
    ******Iframe+Form*******



3、JSONP 跨域Ajax
    
    瀏覽器同源策略:XMLHttpRequest
    巧妙的機制JSONP
    
    JSONP:
        利用建立script塊,在期中執行src屬性爲:遠程url
        函數(返回值)
        
        function 函數(arg){
            
        }
        
        
注意:CORS

 

1、概述

對於WEB應用程序:用戶瀏覽器發送請求,服務器接收並處理請求,而後返回結果,每每返回就是字符串(HTML),瀏覽器將字符串(HTML)渲染並顯示瀏覽器上。html

一、傳統的Web應用java

一個簡單操做須要從新加載全局數據jquery

二、AJAXweb

AJAX,Asynchronous JavaScript and XML (異步的JavaScript和XML),一種建立交互式網頁應用的網頁開發技術方案。ajax

  • 異步的JavaScript:
    使用 【JavaScript語言】 以及 相關【瀏覽器提供類庫】 的功能向服務端發送請求,當服務端處理完請求以後,【自動執行某個JavaScript的回調函數】。
    PS:以上請求和響應的整個過程是【偷偷】進行的,頁面上無任何感知。
  • XML
    XML是一種標記語言,是Ajax在和後臺交互時傳輸數據的格式之一

利用AJAX能夠作:
一、註冊時,輸入用戶名自動檢測用戶是否已經存在。
二、登錄時,提示用戶名密碼錯誤
三、刪除數據行時,將行ID發送到後臺,後臺在數據庫中刪除,數據庫刪除成功後,在頁面DOM中將數據行也刪除。(博客園)數據庫

 

2、原生AJAX和jQuery Ajax請求

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .btn {
            display: inline-block;
            padding: 5px 10px;
            background-color: #2aabd2;
            color: white;
        }
    </style>
</head>
<body>

    <h1>Ajax全套</h1>
    <h3>1.Ajax發送GET請求</h3>
    <div>
        <a class="btn" onclick="AjaxSubmit1();">點我ajax</a>
        <a class="btn" onclick="AjaxSubmit2();">點我XML</a>
    </div>
    <h3>2.Ajax發送POST請求</h3>
    <div>
        <a class="btn" onclick="AjaxSubmit3();">點我ajax</a>
        <a class="btn" onclick="AjaxSubmit4();">點我XML</a>
    </div>

    <script src="/static/js/jquery-3.3.1.js"></script>
    <script>
        function AjaxSubmit1() {
            $.ajax({
                url: "/ajax1",
                type: "GET",
                data: {'p':123, 'v':456},
                success:function (arg) {

                }
            })
        }

        function AjaxSubmit2() {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange=function () {
                if (xhr.readyState == 4) {
                    // 接收完畢服務器返回的數據
                    console.log(xhr.responseText);
                }
            };
            xhr.open('GET', '/ajax1?p=123');
            xhr.send(null)
        }

        function AjaxSubmit3() {
                $.ajax({
                url: "/ajax1/",
                type: "POST",
                data: {'p':123, 'v':456},
                success:function (arg) {

                }
            })
        }
        
        function AjaxSubmit4() {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange=function () {
                if (xhr.readyState == 4) {
                    console.log(xhr.responseText);
                }
            };
            xhr.open('POST', '/ajax1/');
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
            // 若不加setRequestHeader請求頭,request.POST 拿不到數據,request.body 能夠拿到數據
            // 加上setRequestHeader請求頭,request.POST request.body 均可以拿到數據
            xhr.send('p=66666')
        }
        
    </script>

</body>
</html>
index.html
from django.shortcuts import render, redirect, HttpResponse

# Create your views here.

def index(request):
    return render(request, 'index.html')

def ajax1(request):
    print(request.GET)
    print(request.POST)
    print(request.body) # if POST b'p=123&v=456' ;if GET b''
    return HttpResponse('......')
views.py
"""Django_ajaxquantao URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path

from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', views.index),
    path('ajax1/', views.ajax1)
]
urls.py

a.原生Ajax

主要就是使用 【XmlHttpRequest】對象來完成請求的操做,該對象在主流瀏覽器中均存在(除早起的IE),Ajax首次出現IE5.5中存在(ActiveX控件)。django

一、XmlHttpRequest對象介紹json

XmlHttpRequest對象的主要方法:跨域

a. void open(String method,String url,Boolen async)
   用於建立請求
    
   參數:
       method: 請求方式(字符串類型),如:POST、GET、DELETE...
       url:    要請求的地址(字符串類型)
       async:  是否異步(布爾類型)
 
b. void send(String body)
    用於發送請求
 
    參數:
        body: 要發送的數據(字符串類型)
 
c. void setRequestHeader(String header,String value)
    用於設置請求頭
 
    參數:
        header: 請求頭的key(字符串類型)
        vlaue:  請求頭的value(字符串類型)
 
d. String getAllResponseHeaders()
    獲取全部響應頭
 
    返回值:
        響應頭數據(字符串類型)
 
e. String getResponseHeader(String header)
    獲取響應頭中指定header的值
 
    參數:
        header: 響應頭的key(字符串類型)
 
    返回值:
        響應頭中指定的header對應的值
 
f. void abort()
 
    終止請求
View Code

XmlHttpRequest對象的主要屬性:

a. Number readyState
   狀態值(整數)
 
   詳細:
      0-未初始化,還沒有調用open()方法;
      1-啓動,調用了open()方法,未調用send()方法;
      2-發送,已經調用了send()方法,未接收到響應;
      3-接收,已經接收到部分響應數據;
      4-完成,已經接收到所有響應數據;
 
b. Function onreadystatechange
   當readyState的值改變時自動觸發執行其對應的函數(回調函數)
 
c. String responseText
   服務器返回的數據(字符串類型)
 
d. XmlDocument responseXML
   服務器返回的數據(Xml對象)
 
e. Number states
   狀態碼(整數),如:200、404...
 
f. String statesText
   狀態文本(字符串),如:OK、NotFound...
View Code

 

二、跨瀏覽器支持

    • XmlHttpRequest
      IE7+, Firefox, Chrome, Opera, etc.
    • ActiveXObject("Microsoft.XMLHTTP")
      IE6, IE5
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <h1>XMLHttpRequest - Ajax請求</h1>
    <input type="button" onclick="XmlGetRequest();" value="Get發送請求" />
    <input type="button" onclick="XmlPostRequest();" value="Post發送請求" />

    <script src="/statics/jquery-1.12.4.js"></script>
    <script type="text/javascript">

        function GetXHR(){
            var xhr = null;
            if(XMLHttpRequest){
                xhr = new XMLHttpRequest();
            }else{
                xhr = new ActiveXObject("Microsoft.XMLHTTP");
            }
            return xhr;

        }

        function XhrPostRequest(){
            var xhr = GetXHR();
            // 定義回調函數
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4){
                    // 已經接收到所有響應數據,執行如下操做
                    var data = xhr.responseText;
                    console.log(data);
                }
            };
            // 指定鏈接方式和地址----文件方式
            xhr.open('POST', "/test/", true);
            // 設置請求頭
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
            // 發送請求
            xhr.send('n1=1;n2=2;');
        }

        function XhrGetRequest(){
            var xhr = GetXHR();
            // 定義回調函數
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4){
                    // 已經接收到所有響應數據,執行如下操做
                    var data = xhr.responseText;
                    console.log(data);
                }
            };
            // 指定鏈接方式和地址----文件方式
            xhr.open('get', "/test/", true);
            // 發送請求
            xhr.send();
        }

    </script>

</body>
</html>
基於原生Ajax

b.jQuery ajax

jQuery其實就是一個JavaScript的類庫,其將複雜的功能作了上層封裝,使得開發者能夠在其基礎上寫更少的代碼實現更多的功能。

  • jQuery 不是生產者,而是大天然搬運工。
  • jQuery Ajax本質 XMLHttpRequest 或 ActiveXObject 

注:2.+版本再也不支持IE9如下的瀏覽器

jQuery.get(...)
                全部參數:
                     url: 待載入頁面的URL地址
                    data: 待發送 Key/value 參數。
                 success: 載入成功時回調函數。
                dataType: 返回內容格式,xml, json,  script, text, html


            jQuery.post(...)
                全部參數:
                     url: 待載入頁面的URL地址
                    data: 待發送 Key/value 參數
                 success: 載入成功時回調函數
                dataType: 返回內容格式,xml, json,  script, text, html


            jQuery.getJSON(...)
                全部參數:
                     url: 待載入頁面的URL地址
                    data: 待發送 Key/value 參數。
                 success: 載入成功時回調函數。


            jQuery.getScript(...)
                全部參數:
                     url: 待載入頁面的URL地址
                    data: 待發送 Key/value 參數。
                 success: 載入成功時回調函數。


            jQuery.ajax(...)

                部分參數:

                        url:請求地址
                       type:請求方式,GET、POST(1.9.0以後用method)
                    headers:請求頭
                       data:要發送的數據
                contentType:即將發送信息至服務器的內容編碼類型(默認: "application/x-www-form-urlencoded; charset=UTF-8")
                      async:是否異步
                    timeout:設置請求超時時間(毫秒)

                 beforeSend:發送請求前執行的函數(全局)
                   complete:完成以後執行的回調函數(全局)
                    success:成功以後執行的回調函數(全局)
                      error:失敗以後執行的回調函數(全局)
                

                    accepts:經過請求頭髮送給服務器,告訴服務器當前客戶端課接受的數據類型
                   dataType:將服務器端返回的數據轉換成指定類型
                                   "xml": 將服務器端返回的內容轉換成xml格式
                                  "text": 將服務器端返回的內容轉換成普通文本格式
                                  "html": 將服務器端返回的內容轉換成普通文本格式,在插入DOM中時,若是包含JavaScript標籤,則會嘗試去執行。
                                "script": 嘗試將返回值看成JavaScript去執行,而後再將服務器端返回的內容轉換成普通文本格式
                                  "json": 將服務器端返回的內容轉換成相應的JavaScript對象
                                 "jsonp": JSONP 格式
                                          使用 JSONP 形式調用函數時,如 "myurl?callback=?" jQuery 將自動替換 ? 爲正確的函數名,以執行回調函數

                                  若是不指定,jQuery 將自動根據HTTP包MIME信息返回相應類型(an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string

                 converters: 轉換器,將服務器端的內容根據指定的dataType轉換類型,並傳值給success回調函數
                         $.ajax({
                              accepts: {
                                mycustomtype: 'application/x-some-custom-type'
                              },
                              
                              // Expect a `mycustomtype` back from server
                              dataType: 'mycustomtype'

                              // Instructions for how to deserialize a `mycustomtype`
                              converters: {
                                'text mycustomtype': function(result) {
                                  // Do Stuff
                                  return newresult;
                                }
                              },
                            });
jQuery Ajax方法列表
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <p>
        <input type="button" onclick="XmlSendRequest();" value='Ajax請求' />
    </p>


    <script type="text/javascript" src="jquery-1.12.4.js"></script>
    <script>

        function JqSendRequest(){
            $.ajax({
                url: "http://c2.com:8000/test/",
                type: 'GET',
                dataType: 'text',
                success: function(data, statusText, xmlHttpRequest){
                    console.log(data);
                }
            })
        }


    </script>
</body>
</html>
jQuery ajax -demo

 

3、’僞‘Ajax

因爲HTML標籤的iframe標籤具備局部加載內容的特性,因此可使用其來僞造Ajax請求。

實例一

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .btn {
            display: inline-block;
            padding: 5px 10px;
            background-color: #2aabd2;
            color: white;
        }
    </style>
</head>
<body>

    <h1>Ajax全套</h1>
    <h3>1.Ajax發送GET請求</h3>
    <div>
        <a class="btn" onclick="AjaxSubmit1();">點我ajax</a>
        <a class="btn" onclick="AjaxSubmit2();">點我XML</a>
    </div>
    <h3>2.Ajax發送POST請求</h3>
    <div>
        <a class="btn" onclick="AjaxSubmit3();">點我ajax</a>
        <a class="btn" onclick="AjaxSubmit4();">點我XML</a>
    </div>

    <h3>3.僞ajax</h3>
    <div>
       <input type="text" id="url" placeholder="請輸入URL" ><a href="#" onclick="test()">提交</a>
    </div>
    <iframe src="https://www.xiaohua.com/" frameborder="0" style="width: 800px;height: 600px" class="ifram"></iframe>

    <script src="/static/js/jquery-3.3.1.js"></script>
    <script>
        function AjaxSubmit1() {
            $.ajax({
                url: "/ajax1",
                type: "GET",
                data: {'p':123, 'v':456},
                success:function (arg) {

                }
            })
        }

        function AjaxSubmit2() {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange=function () {
                if (xhr.readyState == 4) {
                    // 接收完畢服務器返回的數據
                    console.log(xhr.responseText);
                }
            };
            xhr.open('GET', '/ajax1?p=123');
            xhr.send(null)
        }

        function AjaxSubmit3() {
                $.ajax({
                url: "/ajax1/",
                type: "POST",
                data: {'p':123, 'v':456},
                success:function (arg) {

                }
            })
        }
        
        function AjaxSubmit4() {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange=function () {
                if (xhr.readyState == 4) {
                    console.log(xhr.responseText);
                }
            };
            xhr.open('POST', '/ajax1/');
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
            // 若不加setRequestHeader請求頭,request.POST 拿不到數據,request.body 能夠拿到數據
            // 加上setRequestHeader請求頭,request.POST request.body 均可以拿到數據
            xhr.send('p=66666')
        }

        function test() {
            var con = $('#url').val();
            $('.ifram').attr('src',con);
        }

        
    </script>

</body>
</html>
html

實例二

基於Iframe+Form表單

    <iframe id="iframe" name="ifra"></iframe>
    <form action="/ajax1/" id="fm" method="post" target="ifra">
        <input type="text" name="root" value="1111">
        <a onclick="AjaxSubmit5()">提交</a>
    </form>

    <script>
        function AjaxSubmit5() {
            document.getElementById('fm').submit();
        }
        
    </script>
    <iframe id="iframe" name="ifra"></iframe>
    <form action="/ajax1/" id="fm" method="post" target="ifra">
        <input type="text" name="root" value="1111">
        <input type="submit" value="提交">
    </form>
from django.shortcuts import render, redirect, HttpResponse

# Create your views here.

def index(request):
    return render(request, 'index.html')

def ajax1(request):
    print(request.GET)
    print(request.POST)
    print(request.body) # if POST b'p=123&v=456' ;if GET b''
    ret = {'status': 'OK', 'message': '......'}
    import json
    return HttpResponse(json.dumps(ret))
views.py

onload

    <iframe id="iframe" name="ifra" onload="reloadframe()"></iframe>
    <form action="/ajax1/" id="fm" method="post" target="ifra">
        <input type="text" name="root" value="1111">
        <input type="submit" value="提交">
    </form>

<script>

        function reloadframe() {
            console.log('abcdefg');
        }
</script>
def ajax1(request):
    import time
    time.sleep(4)
    print(request.GET)
    print(request.POST)
    print(request.body) # if POST b'p=123&v=456' ;if GET b''
    ret = {'status': 'OK', 'message': '......'}
    import json
    return HttpResponse(json.dumps(ret))

 

僞ajax

iframe兼容性是最好的

    <iframe id="ifr" name="ifra"></iframe>
    <form action="/ajax1/" id="fm" method="post" target="ifra">
        <input name="root" value="1111">
        <a href="#" onclick="AjaxSubmit5()">提交</a>
    </form>

        function AjaxSubmit5() {
            //$('#ifr').onload=ReloadFrame();
            //$('#fm').submit();
            document.getElementById('ifr').onload=ReloadFrame;
            document.getElementById('fm').submit();

        }

        function ReloadFrame() {
            //console.log(this);
            //console.log(this.contentWindow);
            //console.log(this.contentWindow.document.body.innerHTML);
            //console.log($(this).contents().find('body').html());
            var content = this.contentWindow.document.body.innerHTML;
            var obj = JSON.parse(content);
            if(obj.status == "OK") {
                alert(obj.message);
            }
        }

 

<!DOCTYPE html>
<html>
 
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
    </head>
 
    <body>
 
        <div>
            <p>請輸入要加載的地址:<span id="currentTime"></span></p>
            <p>
                <input id="url" type="text" />
                <input type="button" value="刷新" onclick="LoadPage();">
            </p>
        </div>
 
 
        <div>
            <h3>加載頁面位置:</h3>
            <iframe id="iframePosition" style="width: 100%;height: 500px;"></iframe>
        </div>
 
 
        <script type="text/javascript">
 
            window.onload= function(){
                var myDate = new Date();
                document.getElementById('currentTime').innerText = myDate.getTime();
 
            };
 
            function LoadPage(){
                var targetUrl =  document.getElementById('url').value;
                document.getElementById("iframePosition").src = targetUrl;
            }
 
        </script>
 
    </body>
</html>
View Code

 

4、文件上傳

利用FormData對象上傳文件、字典

document.getElementById('img').files[0];獲得上傳的文件對象

ajax和原生ajax:
    <h3>上傳文件</h3>
    <input type="file" id="img">
    <a class="btn" onclick="AjaxSubmit6();">上傳</a>
    <a class="btn" onclick="AjaxSubmit7()">上傳</a>

    <script src="/static/js/jquery-3.3.1.js"></script>
    <script>
       function AjaxSubmit6() {
            var data = new FormData();
            data.append('k1','v1');
            data.append('k2', 'v2');
            data.append('k3',   document.getElementById('img').files[0]);
            $.ajax({
                url: '/ajax1/',
                type: 'POST',
                data: data,
                success:function (arg) {
                    console.log(arg);
                },
                processData: false,
                contentType: false
            })
        }

        function AjaxSubmit7() {

            var data = new FormData();
            data.append('k1','v1');
            data.append('k2', 'v2');
            data.append('k3', document.getElementById('img').files[0]);

            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange=function () {
                if (xhr.readyState == 4) {
                    console.log(xhr.responseText);
                }
            };
            xhr.open('POST', '/ajax1/');
            //xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
            xhr.send(data)
        }
</script>
上傳文件

form和iframe

    <iframe style="display: none" id="iframe1" name="ifra1"></iframe>
    <form id="fm1" action="/ajax1.html" method="POST" enctype="multipart/form-data" target="ifra1">
        <input type="text" name="k1" />
        <input type="text" name="k2" />
        <input type="file" name="k3" />
        <a onclick="AjaxSubmit8()">提交</a>
    </form>
        function AjaxSubmit8() {
            document.getElementById('iframe1').onload = reloadIframe1;
            document.getElementById('fm1').submit();
        }
        function reloadIframe1() {
            var content = this.contentWindow.document.body.innerHTML;
            var obj = JSON.parse(content);
            console.log(obj);
        }
iframe上傳文件

 

實例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .btn{
            display: inline-block;
            padding: 5px 10px;
            background-color: coral;
            color: white;
        }
    </style>
</head>
<body>
    <h1>Ajax全套</h1>
    <h3>1.Ajax發送GET請求</h3>
    <div>
        <a class="btn" onclick="AjaxSubmit1();">點我</a>
        <a class="btn" onclick="AjaxSubmit2();">點我</a>
    </div>
    <h3>2.Ajax發送POST請求</h3>
    <div>
        <a class="btn" onclick="AjaxSubmit3();">點我</a>
        <a class="btn" onclick="AjaxSubmit4();">點我</a>
    </div>

    <h3>3.莆田</h3>
    <div>

        <h6>基於Iframe+Form表單</h6>
        <iframe id="iframe" name="ifra"></iframe>
        <form id="fm" action="/ajax1.html" method="POST" target="ifra">
            <input name="root" value="111111" />
            <a onclick="AjaxSubmit5()">提交</a>
        </form>

    </div>
    <h3>4.文件上傳</h3>
    <input type="file" id="img" />
    <a class="btn" onclick="AjaxSubmit6();">上傳</a>
    <a class="btn" onclick="AjaxSubmit7();">上傳</a>

    <iframe style="display: none" id="iframe1" name="ifra1"></iframe>
    <form id="fm1" action="/ajax1.html" method="POST" enctype="multipart/form-data" target="ifra1">
        <input type="text" name="k1" />
        <input type="text" name="k2" />
        <input type="file" name="k3" />
        <a onclick="AjaxSubmit8()">提交</a>
    </form>


    <script src="/static/js/jquery-3.1.1.js"></script>
    <script>

        function  AjaxSubmit1() {
            $.ajax({
                url: '/ajax1.html',
                type:'GET',
                data: {'p':123},
                success:function (arg) {

                }
            })
        }

        function AjaxSubmit2() {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                if(xhr.readyState == 4){
                    // 接收完畢服務器返回的數據
                    console.log(xhr.responseText);

                }
            };
            xhr.open('GET','/ajax1.html?p=123');
            xhr.send(null);
        }

        function  AjaxSubmit3() {
            $.ajax({
                url: '/ajax1.html',
                type:'POST',
                data: {'p':123},
                success:function (arg) {

                }
            })
        }

        function AjaxSubmit4() {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                if(xhr.readyState == 4){
                    // 接收完畢服務器返回的數據
                    console.log(xhr.responseText);

                }
            };
            xhr.open('POST','/ajax1.html');
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
            xhr.send("p=456");
        }
        
        function AjaxSubmit5() {
            document.getElementById('iframe').onload = reloadIframe;
            document.getElementById('fm').submit();
        }

        function reloadIframe() {
            // this=當前標籤
            //console.log(ths);
            //console.log(ths.contentWindow);
            //console.log(ths.contentWindow.document.body.innerHTML);
            //console.log($(ths).contents().find('body').html());
            var content = this.contentWindow.document.body.innerHTML;
            var obj = JSON.parse(content);
            if(obj.status){
                alert(obj.message);
            }
        }
        
        function AjaxSubmit6() {
            //document.getElementById('img')[0]
            var data = new FormData();
            data.append('k1','v1');
            data.append('k2','v2');
            data.append('k3',document.getElementById('img').files[0]);

            $.ajax({
                url: '/ajax1.html',
                type: 'POST',
                data:data,
                success:function (arg) {
                    console.log(arg)
                },
                 processData: false,  // tell jQuery not to process the data
                 contentType: false  // tell jQuery not to set contentType

            })
        }

        function AjaxSubmit7() {
            var data = new FormData();
            data.append('k1','v1');
            data.append('k2','v2');
            data.append('k3',document.getElementById('img').files[0]);

            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                if(xhr.readyState == 4){
                    // 接收完畢服務器返回的數據
                    console.log(xhr.responseText);

                }
            };
            xhr.open('POST','/ajax1.html');
            xhr.send(data);
        }
        
        function AjaxSubmit8() {
            document.getElementById('iframe1').onload = reloadIframe1;
            document.getElementById('fm1').submit();
        }
        function reloadIframe1() {
            var content = this.contentWindow.document.body.innerHTML;
            var obj = JSON.parse(content);
            console.log(obj);
        }
    </script>
</body>
</html>
Ajax全套

 

form和iframe文件預覽

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .btn{
            display: inline-block;
            padding: 5px 10px;
            background-color: coral;
            color: white;
        }
    </style>
</head>
<body>

    <iframe style="display: none" id="iframe1" name="ifra1"></iframe>
    <form id="fm1" action="/upload_img.html" method="POST" enctype="multipart/form-data" target="ifra1">
        <input type="file" name="k3" onchange="uploadFile();" />
    </form>
    <h3>預覽</h3>
    <div id="preview">
    </div>
    <script src="/static/js/jquery-3.1.1.js"></script>
    <script>

        function uploadFile() {
            document.getElementById('iframe1').onload = reloadIframe1;
            document.getElementById('fm1').submit();
        }
        function reloadIframe1() {
            var content = this.contentWindow.document.body.innerHTML;
            var obj = JSON.parse(content);

            var tag = document.createElement('img');
            tag.src = obj.data;
            $('#preview').empty().append(tag);
        }
    </script>
</body>
</html>
upload.html
def upload(request):
    return render(request,'upload.html')


def upload_img(request):
    import os
    import uuid
    import json
    nid = str(uuid.uuid4())
    ret = {'status':True,'data':None,'message':None}
    obj = request.FILES.get('k3')

    file_path = os.path.join('static', nid+obj.name)
    f = open(file_path,'wb')
    for line in obj.chunks():
        f.write(line)
    f.close()
    ret['data'] = '/' + file_path
    return HttpResponse(json.dumps(ret))
views.py

 

5、跨域AJAX

因爲瀏覽器存在同源策略機制,同源策略阻止從一個源加載的文檔或腳本獲取或設置另外一個源加載的文檔的屬性。

特別的:因爲同源策略是瀏覽器的限制,因此請求的發送和響應是能夠進行,只不過瀏覽器不接受罷了。

瀏覽器同源策略並非對全部的請求均制約:

  • 制約: XmlHttpRequest
  • 不叼: img、iframe、script等具備src屬性的標籤

跨域,跨域名訪問,如:http://www.c1.com 域名向 http://www.c2.com域名發送請求。

一、JSONP實現跨域請求

JSONP(JSONP - JSON with Padding是JSON的一種「使用模式」),利用script標籤的src屬性(瀏覽器容許script標籤跨域) 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>

    <div id="content"></div>
    <input type="button" value="發送1" onclick="submitJsonp1();" />
    <input type="button" value="發送2" onclick="submitJsonp2();" />
    <input type="button" value="發送3" onclick="submitJsonp3();" />
    <input type="button" value="發送4" onclick="submitJsonp4();" />
    <script src="/static/js/jquery-3.3.1.js"></script>
    <script>
        function submitJsonp1() {
            $.ajax({
                url: '/ajax3.html',
                type: 'GET',
                data: {nid:2},
                success:function (arg) {
                    $('#content').html(arg);
                }
            })
        }

        function submitJsonp2() {
            var tag = document.createElement('script');
            tag.src = 'http://127.0.0.1:9000/xiaokai.html';
            document.head.appendChild(tag);
            document.head.removeChild(tag);
        }

        function fuck(arg) {
            $('#content').html(arg);
        }

        function submitJsonp3() {
            var tag = document.createElement('script');
            tag.src = 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403';
            document.head.appendChild(tag);
            document.head.removeChild(tag);
        }

{#        function list(arg) {#}
{#            console.log(arg);#}
{#        }#}
        
        function submitJsonp4() {
            $.ajax({
                url: 'http://127.0.0.1:9000/xiaokai.html',
                type: 'POST',
                dataType: 'jsonp',
                jsonp: 'callback',
                jsonpCallback: 'func'
            })
        }
        function func(arg) {
            console.log(arg);
        }
    </script>
</body>
</html>
jsonp.html
 
def jsonp(request):
    return render(request,'jsonp.html')

def ajax3(request):
    return HttpResponse('本服務器發送的請求')
views.py

被請求端

from django.shortcuts import render, HttpResponse

# Create your views here.
def xiaokai(request):
    # return HttpResponse('func("hello world")')
    name = request.GET.get('callback')
    return HttpResponse("%s('hello world....')"%name)
views.py

二、CORS

隨着技術的發展,如今的瀏覽器能夠支持主動設置從而容許跨域請求,即:跨域資源共享(CORS,Cross-Origin Resource Sharing),其本質是設置響應頭,

使得瀏覽器容許跨域請求。

簡單請求 OR 非簡單請求

 
條件:
    一、請求方式:HEAD、GET、POST
    二、請求頭信息:
        Accept
        Accept-Language
        Content-Language
        Last-Event-ID
        Content-Type 對應的值是如下三個中的任意一個
                                application/x-www-form-urlencoded
                                multipart/form-data
                                text/plain
 
注意:同時知足以上兩個條件時,則是簡單請求,不然爲複雜請求
 

簡單請求和非簡單請求的區別?

簡單請求:一次請求
非簡單請求:兩次請求,在發送數據以前會先發一次請求用於作「預檢」,只有「預檢」經過後纔再發送一次請求用於數據傳輸。

* 關於「預檢」

 
- 請求方式:OPTIONS
- 「預檢」其實作檢查,檢查若是經過則容許傳輸數據,檢查不經過則再也不發送真正想要發送的消息
- 如何「預檢」
     => 若是複雜請求是PUT等請求,則服務端須要設置容許某請求,不然「預檢」不經過
        Access-Control-Request-Method
     => 若是複雜請求設置了請求頭,則服務端須要設置容許某請求頭,不然「預檢」不經過
        Access-Control-Request-Headers
 

基於cors實現AJAX請求:

a、支持跨域,簡單請求

服務器設置響應頭:Access-Control-Allow-Origin = '域名' 或 '*'

 
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <p>
        <input type="submit" onclick="XmlSendRequest();" />
    </p>

    <p>
        <input type="submit" onclick="JqSendRequest();" />
    </p>

    <script type="text/javascript" src="jquery-1.12.4.js"></script>
    <script>
        function XmlSendRequest(){
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4) {
                    var result = xhr.responseText;
                    console.log(result);
                }
            };
            xhr.open('GET', "http://c2.com:8000/test/", true);
            xhr.send();
        }

        function JqSendRequest(){
            $.ajax({
                url: "http://c2.com:8000/test/",
                type: 'GET',
                dataType: 'text',
                success: function(data, statusText, xmlHttpRequest){
                    console.log(data);
                }
            })
        }


    </script>
</body>
</html>
html
 
class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
        self.write('{"status": true, "data": "seven"}')

b、支持跨域,複雜請求

因爲複雜請求時,首先會發送「預檢」請求,若是「預檢」成功,則發送真實數據。

  • 「預檢」請求時,容許請求方式則需服務器設置響應頭:Access-Control-Request-Method
  • 「預檢」請求時,容許請求頭則需服務器設置響應頭:Access-Control-Request-Headers
  • 「預檢」緩存時間,服務器設置響應頭:Access-Control-Max-Age
 
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <p>
        <input type="submit" onclick="XmlSendRequest();" />
    </p>

    <p>
        <input type="submit" onclick="JqSendRequest();" />
    </p>

    <script type="text/javascript" src="jquery-1.12.4.js"></script>
    <script>
        function XmlSendRequest(){
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4) {
                    var result = xhr.responseText;
                    console.log(result);
                }
            };
            xhr.open('PUT', "http://c2.com:8000/test/", true);
            xhr.setRequestHeader('k1', 'v1');
            xhr.send();
        }

        function JqSendRequest(){
            $.ajax({
                url: "http://c2.com:8000/test/",
                type: 'PUT',
                dataType: 'text',
                headers: {'k1': 'v1'},
                success: function(data, statusText, xmlHttpRequest){
                    console.log(data);
                }
            })
        }


    </script>
</body>
</html>
HTML
 
class MainHandler(tornado.web.RequestHandler):
    
    def put(self):
        self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
        self.write('{"status": true, "data": "seven"}')

    def options(self, *args, **kwargs):
        self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
        self.set_header('Access-Control-Allow-Headers', "k1,k2")
        self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
        self.set_header('Access-Control-Max-Age', 10)
Tornado

c、跨域獲取響應頭

默認獲取到的全部響應頭只有基本信息,若是想要獲取自定義的響應頭,則須要再服務器端設置Access-Control-Expose-Headers。

 
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <p>
        <input type="submit" onclick="XmlSendRequest();" />
    </p>

    <p>
        <input type="submit" onclick="JqSendRequest();" />
    </p>

    <script type="text/javascript" src="jquery-1.12.4.js"></script>
    <script>
        function XmlSendRequest(){
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4) {
                    var result = xhr.responseText;
                    console.log(result);
                    // 獲取響應頭
                    console.log(xhr.getAllResponseHeaders());
                }
            };
            xhr.open('PUT', "http://c2.com:8000/test/", true);
            xhr.setRequestHeader('k1', 'v1');
            xhr.send();
        }

        function JqSendRequest(){
            $.ajax({
                url: "http://c2.com:8000/test/",
                type: 'PUT',
                dataType: 'text',
                headers: {'k1': 'v1'},
                success: function(data, statusText, xmlHttpRequest){
                    console.log(data);
                    // 獲取響應頭
                    console.log(xmlHttpRequest.getAllResponseHeaders());
                }
            })
        }


    </script>
</body>
</html>
HTML
 
class MainHandler(tornado.web.RequestHandler):
    
    def put(self):
        self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")

        self.set_header('xxoo', "seven")
        self.set_header('bili', "daobidao")

        self.set_header('Access-Control-Expose-Headers', "xxoo,bili")


        self.write('{"status": true, "data": "seven"}')

    def options(self, *args, **kwargs):
        self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
        self.set_header('Access-Control-Allow-Headers', "k1,k2")
        self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
        self.set_header('Access-Control-Max-Age', 10)
Tornado

d、跨域傳輸cookie

在跨域請求中,默認狀況下,HTTP Authentication信息,Cookie頭以及用戶的SSL證書不管在預檢請求中或是在實際請求都是不會被髮送。

若是想要發送:

  • 瀏覽器端:XMLHttpRequest的withCredentials爲true
  • 服務器端:Access-Control-Allow-Credentials爲true
  • 注意:服務器端響應的 Access-Control-Allow-Origin 不能是通配符 *
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <p>
        <input type="submit" onclick="XmlSendRequest();" />
    </p>

    <p>
        <input type="submit" onclick="JqSendRequest();" />
    </p>

    <script type="text/javascript" src="jquery-1.12.4.js"></script>
    <script>
        function XmlSendRequest(){
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4) {
                    var result = xhr.responseText;
                    console.log(result);
                }
            };

            xhr.withCredentials = true;

            xhr.open('PUT', "http://c2.com:8000/test/", true);
            xhr.setRequestHeader('k1', 'v1');
            xhr.send();
        }

        function JqSendRequest(){
            $.ajax({
                url: "http://c2.com:8000/test/",
                type: 'PUT',
                dataType: 'text',
                headers: {'k1': 'v1'},
                xhrFields:{withCredentials: true},
                success: function(data, statusText, xmlHttpRequest){
                    console.log(data);
                }
            })
        }


    </script>
</body>
</html>
HTML
class MainHandler(tornado.web.RequestHandler):
    
    def put(self):
        self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
        self.set_header('Access-Control-Allow-Credentials', "true")
        
        self.set_header('xxoo', "seven")
        self.set_header('bili', "daobidao")
        self.set_header('Access-Control-Expose-Headers', "xxoo,bili")

        self.set_cookie('kkkkk', 'vvvvv');

        self.write('{"status": true, "data": "seven"}')

    def options(self, *args, **kwargs):
        self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
        self.set_header('Access-Control-Allow-Headers', "k1,k2")
        self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
        self.set_header('Access-Control-Max-Age', 10)
Tornado
相關文章
相關標籤/搜索