跨域上傳文件
之前解決跨域問題都是使用的JQuery的JSONP
類型的Ajax請(qǐng)求霎箍,JSONP原理是讓服務(wù)器把數(shù)據(jù)放到它動(dòng)態(tài)生成的JS文件中,然后在客戶端中調(diào)用舱权。但是JSONP只支持GET方式的請(qǐng)求逾冬,不適用于上傳文件包吝。
所以后來使用CORS
實(shí)現(xiàn)跨域上傳文件锥余。CORS允許遠(yuǎn)程服務(wù)器定義哪些源站有權(quán)限訪問它的資源腹纳。具體做法是在服務(wù)器端設(shè)置響應(yīng)頭部的Access-Control-Allow-Origin
。設(shè)置為*
表示允許任意外域訪問驱犹,也可以指定允許某個(gè)源站的地址嘲恍,比如Access-Control-Allow-Origin: http://test.example
。
FormData處理文件數(shù)據(jù)
當(dāng)表單中需要上傳文件時(shí)雄驹,可以使用FormData
佃牛,這時(shí)需要在form
標(biāo)簽中指定編碼類型為multipart/form-data
。對(duì)應(yīng)的HTML代碼:
<form name="editUserForm" enctype="multipart/form-data">
<input id="imageUpload" type="file" accept='image/jpg,image/jpeg,image/png,image/svg' class="btn btn-primary" >
</form>
FormData使用也很簡(jiǎn)單医舆,結(jié)合JQuery的POST類型的Ajax請(qǐng)求傳遞數(shù)據(jù)俘侠。對(duì)應(yīng)的js代碼:
var formdata = new FormData();
formdata.append('photo', $("#imageUpload")[0].files[0]);
//也可以添加別的數(shù)據(jù)...
//發(fā)送請(qǐng)求
$.ajax({
type: 'POST',
url: "/api/user/update/",
data: formdata, //用FormData編碼好的數(shù)據(jù)
cache: false, //不緩存
contentType: false, //禁止jQuery的數(shù)據(jù)轉(zhuǎn)換操作(data默認(rèn)轉(zhuǎn)換為query string)
processData: false, //禁止jQuery默認(rèn)的轉(zhuǎn)換過程
error: function() {
console.log('request /api/user/update/ failed!');
},
success: function(data) {
//......
}
})
需要注意的是,
FormData對(duì)象的字段類型可以是
Blob
,File
, 或者string
: 如果它的字段類型不是Blob也不是File彬向,則會(huì)被轉(zhuǎn)換成字符串類型兼贡。
比如我遇到一個(gè)問題就是攻冷,如果字段的值為null
娃胆,傳遞到后端的會(huì)是字符串"null"
,導(dǎo)致保存到數(shù)據(jù)庫里對(duì)應(yīng)的字段內(nèi)容也變成字符串"null"
了等曼,這是個(gè)坑里烦。
FileReader讀取文件并預(yù)覽
如果選擇圖片之后要在當(dāng)前頁面上預(yù)覽,可以使用HTML5的FileReader
實(shí)現(xiàn)禁谦。這里主要使用readAsDataURL(file)
方法胁黑,讀取文件并將文件以數(shù)據(jù)URI的形式保存在result
屬性中,然后在加載文件的事件監(jiān)聽中將result設(shè)置為圖片的src州泊,這樣就能在頁面上看到剛選擇的圖片了丧蘸。
對(duì)應(yīng)的JS代碼:
//上傳照片按鈕的change事件監(jiān)聽,實(shí)現(xiàn)照片預(yù)覽
$("#imageUpload").on('change', function () {
if($(this)[0].files[0].size/(1000) >256){ //限制文件的大小
$.dialog({
title: "哎呀",
content: "上傳的照片應(yīng)小于256KB遥皂!"
});
}else{
if (typeof (FileReader) != "undefined") {
var image_holder = $("#image-holder");
image_holder.empty();
var reader = new FileReader();
reader.onload = function (e) { //FileReader的load事件監(jiān)聽
$("<img />", {
"src": e.target.result,
"class": "thumb-image"
}).appendTo(image_holder);
};
image_holder.show();
reader.readAsDataURL($(this)[0].files[0]); //使用FileReader讀取文件
} else {
$.dialog({
title: "哎呀",
content: "您的瀏覽器不支持FileReader力喷!"
});
}
}
});
file類型的input點(diǎn)擊后彈窗很慢?
使用Chrome演训,點(diǎn)擊選擇文件按鈕之后弟孟,等好幾秒彈窗才出現(xiàn),甚至瀏覽器直接卡死了样悟。后來發(fā)現(xiàn)是因?yàn)樵O(shè)置了accept='image/*'
拂募,解決辦法是指定具體的幾種圖片格式庭猩。比如accept='image/jpg, image/jpeg, image/png, image/svg'
。
參考鏈接
通過HTML5 FileReader實(shí)現(xiàn)上傳圖片預(yù)覽功能
FormData對(duì)象的使用