前言
- 當我們熟練的使用axios,fetch,promise的時候是否還會想起,當年的ajax,讓我們來重溫ajax原理,感受一下經典
http 協議
HTTP協議,即超文字傳輸協議(Hypertext transfer protocol)。是一種詳細規定了瀏覽器和伺服器之間互相通訊的規則
HTTP協議規定了請求 和響應 的標準
請求與請求報文
get請求的請求報文詳解
//--------------------------請求行--------------------------------
// GET 請求方式
// 01.php?username=pp&password=123456 請求路徑+引數(注意點)
// HTTP/1.1 HTTP的版本號
GET /day02/01.php?username=pp&password=123456 HTTP/1.1
//--------------------------請求頭--------------------------------
Host: www.study.com
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,`*/*`;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
//----------------------------請求體-------------------------------------
//get請求沒有請求體,但是引數會拼接到請求行中
複製程式碼
POST請求的請求報文
//-----------------------請求行---------------------------------------------
POST /01.php HTTP/1.1
//-----------------------請求頭--------------------------------------------
Host: www.study.com
Connection: keep-alive
//傳遞的引數的長度。
Content-Length: 29
Cache-Control: max-age=0
Origin: http://www.study.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36
//內容型別:表單資料,如果是post請求,必須指定這個屬性。
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,`*/*`;q=0.8
Referer: http://www.study.com/01-login.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
//------------------------請求體------------------------------------------
username=why&password=123456
複製程式碼
GET請求與POST請求的對比
- GET請求沒有請求體,因為GET請求的引數拼接到位址列中了
- POST請求有請求體,就是傳遞的引數
- POST請求需要指定content-type屬性。
響應與響應報文
//---------------------狀態行(響應行)-------------------------------
//HTTP/1.1 HTTP版本
//200 響應的狀態
//200表示成功
//304表示讀快取
//404表示找不到資源
//500表示服務端錯誤
HTTP/1.1 200 OK
//----------------------響應頭-----------------------------------------------
Date: Thu, 22 May 2019 16:51:22 GMT
Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j PHP/5.4.45
X-Powered-By: PHP/5.4.45
Content-Length: 18
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
//內容型別,告訴瀏覽器該如何解析響應結果
Content-Type: text/html;charset=utf-8
//-----------------------響應體------------------------------------------------
hello world
複製程式碼
AJAX
即 Asynchronous [e'sɪŋkrənəs] Javascript And XML, AJAX 不是一門的新的語言,而是對現有技術的綜合利用。 本質是在HTTP協議的基礎上以非同步的方式與伺服器進行通訊。
同步與非同步
同步和非同步概念:
同步: 指的就是事情要一件一件做。等做完前一件才能做後一件任務
非同步: 不受當前任務的影響,兩件事情同時進行,做一件事情時,不影響另一件事情的進行。
程式設計中:非同步程式程式碼執行時不會阻塞其它程式程式碼執行,從而提升整體執行效率。
網頁非同步應用:
- 驗證你的使用者名稱是否已經存在(一邊輸入,一邊獲取你的資訊,和後臺比對)。
- 百度搜尋提示,及相關內容展示(一邊輸入,一邊找出了你可能要的內容)。
- 新浪微博評論(非同步載入)。
XMLHttpRequest可以以非同步方式的請求資料處理程式, 可實現對網頁的部分更新, 而不是重新整理整個頁面
XMLHttpRequest物件
瀏覽器內建物件,用於與伺服器通訊(交換資料) , 由此我們便可實現對網頁的部分更新,而不是重新整理整個頁面。這個請求是非同步的,即在往伺服器傳送請求時,並不會阻礙程式的執行,瀏覽器會繼續渲染後續的結構。
請求由客戶端發起,其規範格式為:請求行、請求頭、請求主體。
複製程式碼
傳送get請求
XMLHttpRequest以非同步的方式傳送HTTP請求,因此在傳送請求時,一樣需要遵循HTTP協議。
使用XMLHttpRequest傳送get請求的步驟
//1. 建立一個XMLHttpRequest物件
var xhr = new XMLHttpRequest();
//2. 設定請求行
// 第一個引數:請求方式 get/post
// 第二個引數:請求的地址 需要在url後面拼上引數列表
xhr.open("get", "01.php?name=why");
//3. 設定請求頭
//請求頭中可以設定Content-Type,用以說明請求主體的內容是如何編碼,get請求時沒有請求體,無需設定
//4. 設定請求體
//get請求的請求體為空,因為引數列表拼接到url後面了
xhr.send(null);
複製程式碼
注意點 :
- get請求,設定請求行時,需要把引數列表拼接到url後面
- get請求不用設定請求頭, 不用說明請求主體的編碼方式
- get請求的請求體為null
傳送post請求
var xhr = new XMLHttpRequest();
// 1. 設定請求行 post請求的引數列表在請求體
xhr.open("post", "02.php");
// 2. 設定請求頭, post 請求必須要設定 content-type, 標記請求體內容的解析方式, 不然後端無法解析獲取資料
xhr.setRequestHeader( "content-type", "application/x-www-form-urlencoded" );
// 3. 設定請求體
xhr.send( "name=Jepson&age=18" );
複製程式碼
注意點 :
- post請求, 設定請求行時, 不拼接引數列表
- post必須設定請求頭中的content-type為application/x-www-form-urlencoded, 標記請求體解析方式
- post 請求需要將引數列表設定到請求體中
獲取響應 readyState
readyState:記錄了XMLHttpRequest物件的當前狀態
readyState有五種可能的值:
xhr.readyState = 0時,UNSENT open尚未呼叫
xhr.readyState = 1時,OPENED open已呼叫
xhr.readyState = 2時,HEADERS_RECEIVED 接收到頭資訊
xhr.readyState = 3時,LOADING 接收到響應主體
xhr.readyState = 4時,DONE 響應完成
不用記憶狀態,只需要瞭解有狀態變化這個概念
複製程式碼
HTTP響應分為3個部分,狀態行、響應頭、響應體。
//給xhr註冊一個onreadystatechange事件,當xhr的狀態發生狀態發生改變時,會觸發這個事件。
xhr.onreadystatechange = function () {
if(xhr.readyState == 4){
//1. 獲取狀態行
console.log("狀態行:"+xhr.status);
//2. 獲取響應頭
console.log("所有的響應頭:"+xhr.getAllResponseHeaders());
console.log("指定響應頭:"+xhr.getResponseHeader("content-type"));
//3. 獲取響應體
console.log(xhr.responseText);
}
}
複製程式碼
資料互動
瀏覽器端只是負責使用者的互動和資料的收集以及展示,真正的資料都是儲存在伺服器端的。
我們現在通過ajax的確可以返回一些簡單的資料(一個字串),
但是在實際開發過程中,肯定會會設計到大量的複雜型別的資料傳輸,
比如陣列、物件等,但是每個程式語言的語法都不一樣。
因此我們會採用通過的資料交換格式(XML、JSON)來進行資料的互動。
複製程式碼
XML(瞭解即可,現在很少見)
什麼是XML
- XML 指可擴充套件標記語言(EXtensible Markup Language)
- XML 是一種標記語言,很類似 HTML
- XML 的設計宗旨是傳輸資料,而非顯示資料
- XML 標籤沒有被預定義。您需要自行定義標籤。
語法規範
- 第一行必須是版本資訊
- 必須有一個根元素(有且僅有一個)
- 標籤不可有空格、不可以數字或.開頭、大小寫敏感
- 不可交叉巢狀,都是雙標籤,如果是單標籤,必須閉合
- 屬性雙引號(瀏覽器自動修正成雙引號了)
- 特殊符號要使用實體
- 註釋和HTML一樣
<?xml version="1.0" encoding="utf-8" ?>
<students>
<student>
<name>張三</name>
<age>18</age>
<gender>男</gender>
<desc>路人甲</desc>
</student>
<student>
<name>李四</name>
<age>20</age>
<gender>男</gender>
<desc>路人乙</desc>
</student>
</students>
複製程式碼
php獲取xml檔案的內容
// 注意: 如果需要返回 xml 資料, 需要將 content-type 改成 text/xml, 不然瀏覽器以 text/html 解析
header( 'content-type:text/xml;charset=utf-8' );
// file_get_content 用於獲取檔案的內容
// 引數: 檔案的路徑
$result = file_get_content( "data.xml" );
echo $result;
複製程式碼
js解析xml
//獲取服務端返回的xml資料,需要使用xhr.responseXML,這是一個document物件,可以使用DOM中的方法查詢元素。
var data = xhr.responseXML;
//獲取所有的學生
var students = data.querySelectorAll("student");
複製程式碼
缺點:雖然可以描述和傳輸複雜資料,但是其解析過於複雜, 並且體積較大,所以實現開發已經很少使用了。
JSON資料
JSON(JavaScript Object Notation, JS 物件標記) 是一種輕量級的資料交換格式。它基於 ECMAScript 規範,採用獨立於程式語言的文字格式來儲存和表示資料。
- 資料在 鍵值對 中
- 資料由逗號分隔(最後一個 鍵值對 不能帶逗號)
- 花括號儲存物件,方括號儲存陣列
- 鍵使用雙引號
var obj = {a: 'Hello', b: 'World'}; //這是一個物件
// 這是一個 JSON 字串,本質是一個字串
var json = '{"a": "Hello", "b": "World"}';
複製程式碼
JSON資料在不同語言進行傳輸時,型別為字串,不同的語言各自也都對應有解析方法,解析完成後就能很方便的使用了
php處理json
- php關聯陣列 ==> json ( json_encode )
// php的關聯陣列
$obj = array(
"a" => "hello",
"b" => "world",
"name" => "why"
);
//json字串
$json = json_encode( $obj );
echo $json;
複製程式碼
- json ==> php物件/關聯陣列 ( json_decode )
$json = '{"a": "Hello", "b": "World"}';//json字串
//第一個引數:json字串
//第二個引數:
//false,將json轉換成物件(預設)
//true:將json轉換成陣列(推薦)
$obj = json_decode($json,true);
echo $obj['a'];
//通過json檔案獲取到的內容就是一個json字串。
$data = file_get_contents("data.json");
//將json轉換成陣列
$result = json_decode($data, true);
print_r($result);
複製程式碼
JS處理json
- JS物件 ==> JSON字串 JSON.stringify(obj)
//obj是一個js物件
var obj = {a: 'Hello', b: 'World'}
//result就變成了一個json字串了
var result = JSON.stringify(obj);// '{"a": "Hello", "b": "World"}'
複製程式碼
- JSON字串 ==> JS物件 JSON.parse(obj)
//json是一個json字串
var json = '{"a": "Hello", "b": "World"}';
//obj就變成了一個js物件
var obj = JSON.parse(json);// {a: 'Hello', b: 'World'}
複製程式碼
相容性處理
現在一般最多相容到 IE8, 這裡以後見到了知道是在處理相容性就行了
var xhr = null;
if(XMLHttpRequest){
//現代瀏覽器 IE7+
xhr = new XMLHttpRequest();
}else{
//老版本的 Internet Explorer (IE5 和 IE6)使用 ActiveX 物件:
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
複製程式碼
封裝ajax工具函式
每次傳送ajax請求,其實步驟都是一樣的,重複了大量程式碼,我們完全可以封裝成一個工具函式。
//1. 建立xhr物件
//2. 設定請求行
//3. 設定請求頭
//3. 設定請求體
//4. 監聽響應狀態
//5. 獲取響應內容
複製程式碼
引數提取
引數名 | 引數型別 | 描述 | 傳值 | 預設值 |
---|---|---|---|---|
type | string | 請求方式 | get/post | 只要不傳post,就是get |
url | string | 請求地址 | 介面地址 | 如果不傳地址,不傳送請求 |
async | boolean | 是否非同步 | true/fase | 只要不傳false,那就是true,非同步請求 |
data | object | 請求資料 | {key:value,key1:value2} |
需要把這個物件拼接成引數的格式 uname=hucc&upass=12345 |
dataType | string | 返回的資料型別 | xml/json/text | text |
success | function | 響應成功時呼叫 | - | - |
error | function | 響應失敗時呼叫 | - | - |
引數檢測
// 要求引數obj必須傳遞,否則直接不傳送請求
if(!obj || typeof obj !== "object"){
return;
}
// 如果type傳遞的是post,那就傳送post請求,否則傳送get請求
var type = obj.type == "post"?"post":'get';
var url = obj.url;
if(!url){
return;
}
// 只有當async傳遞了false,才會傳送同步請求,不然只傳送非同步請求
var async = obj.async == false? false:true;
複製程式碼
完整版本
var $ = {
ajax: function (options) {
//如果options引數沒有傳遞,直接返回。
if (!options || typeof options !== "object") {
return;
}
//處理預設引數
//如果引數不是post,那就預設為get
var type = options.type == "post" ? "post" : "get";
//如果沒有傳url,那就傳當前地址
var url = options.url || location.pathname;
//如果引數不是false,那就預設是true,發非同步請求
var async = options.async == false ? false : true;
var params = this.getParams(options.data);
var xhr = new XMLHttpRequest();
//設定請求行
if (type == "get") {
url = url + "?" + params;
}
xhr.open(type, url, async);
//設定請求頭
if (type == "post") {
xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded");
}
//設定請求引數
xhr.send(params);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
/*根據響應頭的content-type屬性指定方法接收到的內容*/
var contentType = xhr.getResponseHeader('content-type');
var data = null;
if (contentType.indexOf('json') > -1) {
data = JSON.parse(xhr.responseText);
} else if (contentType.indexOf('xml') > -1) {
data = xhr.responseXML;
} else {
data = xhr.responseText;
}
/*執行成功函式*/
options.success && options.success(data);
} else {
options.error && options.error(xhr.responseText);
}
}
}
},
getParams: function (obj) {
//將obj物件轉換成引數
//將物件轉換成引數列表
if (!obj) {
return null;
}
var arr = [];
for (var k in obj) {
arr.push(k + "=" + obj[k]);
}
return arr.join("&");
}
}
複製程式碼
jQuery中的ajax方法
jQuery為我們提供了更強大的Ajax封裝
$.ajax
引數列表
引數名稱 | 描述 | 取值 | 示例 |
---|---|---|---|
url | 介面地址 | url:"02.php" | |
type | 請求方式 | get/post | type:"get" |
timeout | 超時時間 | 單位毫秒 | timeout:5000 |
dataType | 伺服器返回的格式 | json/xml/text(預設) | dataType:"json" |
data | 傳送的請求資料 | 物件 | data:{name:"zs", age:18} |
beforeSend | 呼叫前的回撥函式 | function(){} | beforeSend:function(){ alert(1) } |
success | 成功的回撥函式 | function (data) {} | success:function (data) {} |
error | 失敗的回撥函式 | function (error) {} | error:function(data) {} |
complete | 完成後的回撥函式 | function () {} | complete:function () {} |
使用示例:
$.ajax({
type:"get",//請求型別
url:"02.php",//請求地址
data:{name:"zs", age:18},//請求資料
dataType:"json",//希望接受的資料型別
timeout:5000,//設定超時時間
beforeSend:function () {
//alert("傳送前呼叫");
},
success:function (data) {
//alert("成功時呼叫");
console.log(data);
},
error:function (error) {
//alert("失敗時呼叫");
console.log(error);
},
complete:function () {
//alert("請求完成時呼叫");
}
});
複製程式碼
其他api
//$.post(url, callback, [dataType]);只傳送post請求
//$.get(url, callback, [dataType]);
//$.getJSON(url, callback);
//$.getScript(url,callback);//載入伺服器端的js檔案
//$("div").load(url);//載入一個伺服器端的html頁面。
複製程式碼
同源與跨域
同源
同源策略的基本概念
1995年,同源政策由 Netscape 公司引入瀏覽器。目前,所有瀏覽器都實行這個政策。 同源策略:最初,它的含義是指,A網頁設定的 Cookie,B網頁不能開啟,除非這兩個網頁"同源"。所謂"同源"指的是"三個相同"。
協議相同
域名相同
埠相同
複製程式碼
舉例來說,這個網址http://www.example.com/dir/page.html
協議是http://
,
域名是www.example.com
,埠是80
(預設埠可以省略)。它的同源情況如下。
http://www.example.com/dir2/other.html:同源
file:///F:/phpStudy/WWW//04.html 不同源(協議不同)
http://v2.www.example.com/dir/other.html:不同源(域名不同)
http://www.example.com:81/dir/other.html:不同源(埠不同)
複製程式碼
同源策略的目的
同源政策的目的,是為了保證使用者資訊的安全,防止惡意的網站竊取資料。
同源策略的限制範圍
隨著網際網路的發展,“同源策略”越來越嚴格,目前,如果非同源,以下三種行為都將收到限制。
1. Cookie、LocalStorage 和 IndexDB 無法讀取。
2. DOM 無法獲得。
3. AJAX 請求不能傳送。
複製程式碼
雖然這些限制是很有必要的,但是也給我們日常開發帶來不好的影響。比如實際開發過程中,往往都會把伺服器端架設到一臺甚至是一個叢集的伺服器中,把客戶端頁面放到另外一個單獨的伺服器。那麼這時候就會出現不同源的情況,如果我們知道兩個網站都是安全的話,我們是希望兩個不同源的網站之間可以相互請求資料的。這就需要使用到跨域 。
跨域
jsonp( 無相容性問題 )
JSONP(JSON with Padding)、可用於解決主流瀏覽器的跨域資料訪問的問題。
原理:服務端返回一個定義好的js函式的呼叫,並且將伺服器的資料以該函式引數的形式傳遞過來,這個方法需要前後端配合
script
標籤是不受同源策略的限制的,它可以載入任意地方的 JavaScript 檔案。類似的還有img
和link
標籤
<!--不受同源策略限制的標籤-->
<img src="http://www.api.com/1.jpg" alt="">
<link rel="stylesheet" href="http://www.api.com/1.css">
<script src="http://www.api.com/1.js"></script>
複製程式碼
jsonp演化過程1
php檔案
header("content-type:text/html;charset=utf-8");
echo "alert(1111)";
複製程式碼
html檔案
<script src="http://www.api.com/testjs.php"></script>
複製程式碼
原理:其實src的路徑是什麼檔案不重要,無論引入js檔案還是php檔案,最後返回給瀏覽器的都是字串,因此我們script標籤是可以引入一個php檔案的。
jsonp演化過程2
php檔案
header("content-type:text/html;charset=utf-8");
echo "var a = 118;";
複製程式碼
html檔案
<script src="http://www.api.com/testjs.php"></script>
<script>
//a列印出來了118
console.log(a);
</script>
複製程式碼
我們現在做到了一件事情,從不同源的php檔案中獲取到了資料
缺點:獲取資料的script標籤必須寫在使用的script標籤的前面,必須保證先有資料才能對資料進行渲染。
jsonp演化過程3
php程式碼
header("content-type:text/html;charset=utf-8");
$arr = array(
"name"=>"zs",
"age"=>18
);
$result = json_encode($arr);
//這是一段js函式的呼叫的程式碼,$result就是我們想要的資料
echo "func($result)";
複製程式碼
js程式碼
<script>
function func(data) {
console.log(data);
}
</script>
<script src="http://www.api.com/testjs.php"></script>
複製程式碼
缺點:後端必須知道前端宣告的方法的名字,後端才能呼叫。
jsonp演化過程4
php程式碼
header("content-type:text/html;charset=utf-8");
$arr = array(
"name"=>"zs",
"age"=>18
);
$result = json_encode($arr);
//這是一段js函式的呼叫的程式碼,$result就是我們想要的資料
echo $_GET['callback']."($result)";
複製程式碼
javascript程式碼
function fun(data) {
console.log(data);
}
var button = document.querySelector("button");
button.onclick = function () {
var script = document.createElement("script");
script.src = "http://www.api.com/testjs.php?callback=fun";
document.body.appendChild(script);
}
複製程式碼
- 說白了,jsonp的原理就是 藉助了script標籤 src 請求資源時, 不受同源策略的限制.
- 在服務端返回一個函式的呼叫,將資料當前呼叫函式的實參。
- 在瀏覽器端,需要程式要宣告一個全域性函式,通過形參就可以獲取到服務端返回的對應的值
jsonp原理大家需要知道,但不用太過於去糾結這個原理,因為jquery已經幫我們封裝好了,我們使用起來非常的方便。
jquery對於jsonp的封裝
//使用起來相當的簡單,跟普通的get請求沒有任何的區別,只需要把dataType固定成jsonp即可。
$.ajax({
type:"get",
url:"http://www.why.com/testjs.php",
dataType:"jsonp",
data:{
uname:"why",
upass:"123456"
},
success:function (info) {
console.log(info);
}
});
複製程式碼
XMLHttpRequest2.0
XMLHttpRequest是一個javascript內建物件,使得Javascript可以進行非同步的HTTP通訊。2008年2月,就提出了XMLHttpRequest Level 2 草案。
老版本的XMLHttpRequest的缺點:
1. 僅支援傳輸文字資料,無法傳說二進位制檔案,比如圖片視訊等。
2. 傳輸資料時,沒有進度資訊,只能提示完成與否。
3. 受到了"同源策略"的限制
複製程式碼
新版本的功能:
1. 可以設定timeout超時時間
2. 可以使用formData物件管理表單資料
3. 允許請求不同域名下的資料(跨域)
4. 支援上傳二進位制檔案
5. 可以獲取資料傳輸的進度資訊
複製程式碼
注意:我們現在使用new XMLHttpRequest建立的物件就是2.0物件了,我們之前學的是1.0的語法,現在學習一些2.0的新特性即可。
timeout設定超時
xhr.timeout = 3000;//設定超時時間
xhr.ontimeout = function(){
alert("請求超時");
}
複製程式碼
formData管理表單資料
formData物件類似於jquery的serialize方法,用於管理表單資料
使用特點:
1. 例項化一個formData物件, new formData(form); form就是表單元素
2. formData物件可以直接作為 xhr.send(formData)的引數。注意此時資料是以二進位制的形式進行傳輸。
3. formData有一個append方法,可以新增引數。formData.append("id", "1111");
4. 這種方式只能以post形式傳遞,不需要設定請求頭,瀏覽器會自動為我們設定一個合適的請求頭。
複製程式碼
程式碼示例:
//1. 使用formData必須傳送post請求
xhr.open("post", "02-formData.php");
//2. 獲取表單元素
var form = document.querySelector("#myForm");
//3. 建立form物件,可以直接作為send的引數。
var formData = new FormData(form);
//4. formData可以使用append方法新增引數
formData.append("id", "1111");
//5. 傳送,不需要指定請求頭,瀏覽器會自動選擇合適的請求頭
xhr.send(formData);
複製程式碼
檔案上傳
以前,檔案上傳需要藉助表單進行上傳,但是表單上傳是同步的,也就是說檔案上傳時,頁面需要提交和重新整理,使用者體驗不友好,xhr2.0中的formData物件支援檔案的非同步上傳。
var formData = new FormData();
//獲取上傳的檔案,傳遞到後端
var file = document.getElementById("file").files[0];
formData.append("file", file);
xhr.send(formData);
複製程式碼
顯示檔案進度資訊
xhr2.0還支援獲取上傳檔案的進度資訊,因此我們可以根據進度資訊可以實時的顯示檔案的上傳進度。
1. 需要註冊 xhr.upload.onprogress = function(e){} 事件,用於監聽檔案上傳的進度.注意:需要在send之前註冊。
2. 上傳的進度資訊會儲存事件物件e中
3. e.loaded表示已上傳的大小 e.total表示整個檔案的大小
複製程式碼
程式碼參考:
xhr.upload.onprogress = function (e) {
inner.style.width = (e.loaded/e.total*100).toFixed(2)+"%";
span.innerHTML = (e.loaded/e.total*100).toFixed(2)+"%";
}
xhr.send(formData);
複製程式碼
如果上傳檔案超過8M,php會報錯,需要進行設定,允許php上傳大檔案。
跨域資源共享(CORS) ( 相容性IE10+ )
cors的使用
新版本的XMLHttpRequest物件,可以向不同域名的伺服器發出HTTP請求。這叫做"跨域資源共享"(Cross-origin resource sharing,簡稱CORS)。
跨域資源共享(CORS)的前提
- 瀏覽器支援這個功能( 相容性IE10+ )
- 伺服器必須允許這種跨域。
伺服器允許跨域的程式碼:
//允許所有的域名訪問這個介面
header("Access-Control-Allow-Origin:*");
//允許www.study.com這個域名訪問這個介面
header("Access-Control-Allow-Origin:http://www.study.com");
複製程式碼
CORS的具體流程(瞭解)
-
瀏覽器傳送跨域請求
-
伺服器端收到一個跨域請求後,在響應頭中新增Access-Control-Allow-Origin Header資源許可權配置。傳送響應
-
瀏覽器收到響應後,檢視是否設定了
header('Access-Control-Allow-Origin:請求源域名或者*');
如果當前域已經得到授權,則將結果返回給JavaScript。否則瀏覽器忽略此次響應。
結論:
- 跨域行為是瀏覽器行為,響應式回來了的, 只是瀏覽器安全機制做了限制, 對於跨域響應內容進行了忽略。
- 伺服器與伺服器之間是不存在跨域的問題的
jsonp與cors的對比
- jsonp相容性好,老版本瀏覽器也支援,但是jsonp僅支援get請求,傳送的資料量有限。使用麻煩
- cors需要瀏覽器支援cors功能才行。但是使用簡單,只要服務端設定允許跨域,對於客戶端來說,跟普通的get、post請求並沒有什麼區別。
- 跨域的安全性問題:因為跨域是需要服務端配合控制的 ,也就是說不論jsonp還是cors,如果沒有服務端的允許,瀏覽器是沒法做到跨域的。
其他的跨域手段
以下方式基本不用啊,瞭解即可:
1、頂級域名相同的可以通過domain.name來解決,即同時設定 domain.name = 頂級域名(如example.com) 2、document.domain + iframe 3、window.name + iframe 4、location.hash + iframe 5、window.postMessage()