如果不考慮ie9兼容性,實(shí)現(xiàn)【上傳圖片】大致的思路如下:
- 由于公司是將所有上傳的圖片都放到【代理服務(wù)器】里竟闪。所以【上傳圖片】其實(shí)是上傳到【代理服務(wù)器】离福。可以通過ajax炼蛤,通過FormData將圖片上傳到【代理服務(wù)器】妖爷。
- 從【代理服務(wù)器】拿到的回調(diào)里,有壓縮過的圖片的url,將這個(gè)url賦值給DOM里圖片img的src就行了絮识。由于我們的項(xiàng)目是用的vue绿聘,直接綁定:src就行了。
- 上傳圖片到【代理服務(wù)器】完成后次舌,需要將url等相關(guān)數(shù)據(jù)(我們的項(xiàng)目后端需要一個(gè)pid熄攘,來實(shí)現(xiàn)用戶下次訪問時(shí),后端從代理服務(wù)器根據(jù)這個(gè)pid來獲取相應(yīng)圖片】)彼念,通過ajax發(fā)給后端(我們公司的服務(wù)器)挪圾。
思路很簡單,而且核心關(guān)鍵其實(shí)就是第1點(diǎn)逐沙,第2哲思,3只是簡單的DOM操作和ajax交換數(shù)據(jù)。接下來就只關(guān)注第1點(diǎn)的具體實(shí)現(xiàn)吩案。
1. 通過formData棚赔,結(jié)合html5的input type=file來實(shí)現(xiàn)上傳
<input name="file" type="file" @change="update" accept="image/x-png, image/jpg, image/jpeg">
對應(yīng)的,Vue的methods里务热,update方法如下:
update(e) {
let file = e.target.files[0]; //input提供的API忆嗜,如果需要過濾圖片尺寸,也可以在e.target.files[0]里拿到相應(yīng)數(shù)據(jù)崎岂。
let param = new FormData(); //通過FormData來將圖片信息發(fā)送給服務(wù)器捆毫;FormData是html5的私有對象。
param.append('file', file, file.name);
/* 接下來冲甘,就是通過ajax绩卤,發(fā)送form數(shù)據(jù)到服務(wù)器,我們公司用的jQuery江醇,比較普遍的應(yīng)該是axios吧 */
$.ajax({
url: '/image/upload',
type: 'POST',
data: param, //保證data格式為FormData
processData: false, //必須false才會自動加上正確的Content-Type
contentType: false //必須false才會避開jQuery對 formdata 的默認(rèn)處理
}).done(function(res) {
// 回調(diào)
})
}
然后濒憋,在回調(diào)里,給DOM里的圖片src賦值就行了陶夜。
當(dāng)然凛驮,如果不兼容ie9,現(xiàn)在這個(gè)方案就行了条辟。
在ie9下黔夭,不支持FormData。所以在ie9下羽嫡,只能通過form表單形式實(shí)現(xiàn)圖片上傳本姥。
2. ie9下通過form表單實(shí)現(xiàn)圖片上傳
<form id="myForm" method="post" action="/image/ieupload" enctype="multipart/form-data">
<input name="file" type="file" @change="update" accept="image/x-png, image/jpg, image/jpeg">
<input id="submit" type="submit" style="display:none">
</form>
form里,enctype必須為mulitpart/form-data杭棵,表單中enctype="multipart/form-data"的意思婚惫,是設(shè)置表單的MIME編碼。默認(rèn)情況,這個(gè)編碼格式是application/x-www-form-urlencoded先舷,不能用于文件上傳艰管;只有使用了multipart/form- data,才能完整的傳遞文件數(shù)據(jù)蒋川。
同時(shí)要加上input type="submit"蛙婴,只有點(diǎn)擊(或者trigger click)這個(gè)按鈕,才會將數(shù)據(jù)發(fā)送到服務(wù)器尔破。
這樣街图,在上面的update方法里,就需要加一層判斷懒构,如果不是ie9(或者是瀏覽器不支持formData)餐济,就通過formData結(jié)合ajax實(shí)現(xiàn)上傳圖片。通過formData的好處是不用在DOM里寫form胆剧,(form表單提交絮姆,一般的服務(wù)器處理方式是重定向),只通過ajax跟后端服務(wù)器交換數(shù)據(jù)可以讓接口更加統(tǒng)一秩霍。而如果是ie9篙悯,則必須要通過form表單提交,在update方法里铃绒,通過trigger #submit元素的click事件來完成表單提交鸽照。
但是,如果服務(wù)器返回的是json颠悬,并不能拿到服務(wù)器返回的數(shù)據(jù)矮燎,而是直接提示下載或打開:
之所以ie9下提示打開或者保持赔癌,是因?yàn)椋?br> ie無法解析回調(diào)里的json數(shù)據(jù)诞外,就是說如果服務(wù)器返回json數(shù)據(jù),ie會把它當(dāng)做文件來處理灾票,顯示打開或保存峡谊。
解決方法如下:
在后端返回的時(shí)候自定義contype-type為"text/html",比如在node中這樣寫res.setHeader('Content-Type', 'text/html')刊苍。
參考資料:文件上傳返回JSON數(shù)據(jù)既们,在IE下提示下載文件
這樣改完之后,會發(fā)現(xiàn)班缰,雖然現(xiàn)在不提示下載文件了贤壁,可是會直接跳轉(zhuǎn)到新頁面悼枢。
在ajax未誕生前埠忘,都是用iframe來實(shí)現(xiàn)無刷新的效果。為了避免跳轉(zhuǎn)到新頁面,需要手動指定跳轉(zhuǎn)的頁面為一個(gè)iframe莹妒。然后取到iframe里的回調(diào)內(nèi)容后名船,將相應(yīng)內(nèi)容從iframe里取出來使用。
參考資料:通過iframe防止form表單提交時(shí)跳轉(zhuǎn)頁面
另外旨怠,由于因?yàn)閒ile是Readonly渠驼,如果用戶上傳的圖片不符合要求,想清空value鉴腻,只能用新的file替換之前的file迷扇。
參考資料:http://www.cnblogs.com/nsky/archive/2012/12/28/2836578.html
3. 拓展:本地預(yù)覽(fileReader)
fileReader就是html5為我們提供的讀取文件的api。它的作用就是把文本流按指定格式讀取到緩存爽哎,以供js調(diào)用蜓席。
參考資料:上傳圖片本地預(yù)覽
通過fileReader的readAsDataURL方法,將文件讀取為 DataURL课锌,然后賦值給img的src厨内,就大功告成啦。
DataURL有其固定的格式渺贤,如下:
data:[文件格式];base64,[文本流base64編碼]雏胃。