前言
對于XMLHttpRequest API大家都熟,它是ajax技術(shù)的根本。XMLHttpRequest的第一代不支持文件上傳,所以,只實現(xiàn)了第一代的瀏覽器中無論怎樣使用jQuery.ajax()也不可能上傳文件。所以,討論jQuery.ajax()的上傳文件能力,默認基于第二代API。第二代XHR利用new FormData()來上傳文件。
也就是說,只有jQuery.ajax() + 第二代XHR才可能實現(xiàn)文件上傳。
有人說為啥不直接用原生JS,其實寫起來比$.ajax()的行數(shù)還要少。但是原生JS肯定沒辦法用jq封裝的then方法和其他一些方法,不要小看封裝。
操作
先new一個FormData對象,然后向里面壓入1個文件,然后用jQuery.ajax()方法上傳這個FormData對象即可。
HTML:
<input type="file" id="myfile">
<button>upload</button>
JavaScript:
$('button').click(function() {
var formData = new FormData();
// 鍵名不一定是“file”,可以是任意名;寫多行就可以壓入多個文件,鍵名不可重名
formData.append('file',$('#myfile')[0].files[0]);
$.ajax({
url: '1.php',
type: 'POST',
data: formData,
cache: false,
processData: false, // 要求jQuery不處理發(fā)送的數(shù)據(jù)
contentType: false // 要求jQuery不設(shè)置Content-Type請求頭
}).then(function(data) {
console.log(data);
});
});
所以,關(guān)鍵的知識點其實就兩個,也就是要求jQuery不處理發(fā)送的數(shù)據(jù)和要求jQuery不設(shè)置Content-Type請求頭。
要求jQuery不處理發(fā)送的數(shù)據(jù)是為了不讓jQuery把文件處理成字符串
要求jQuery不設(shè)置Content-Type請求頭是為了不讓jQuery用默認的請求頭
進階
如果你的form表單是標準表單,你還可以有更簡單的js寫法:
var formData = new FormData();這句可以改成var formData = new FormData(document.getElementById('form1'));,也就是說,直接把form元素傳給構(gòu)造器就行了,剩下的事就不用管了,省去了所有的formData.append(...),是不是更方便?
注意事項
最后強調(diào),上述代碼只在支持XHR 2的瀏覽器中才可以正常運行,不支持XHR 2的瀏覽器沒有任何辦法用XHR上傳文件。判斷瀏覽器是否支持XHR 2的最好辦法是下面兩種方法,其中第一種更嚴格,第二種方法執(zhí)行速度更快。我建議使用第一種:
// 注意大小寫
if ( window.hasOwnProperty('FormData') ) {
// ...
}
// 注意大小寫
if ( 'FormData' in window ) {
// ...
}