前言
在前端開發(fā)中冠桃,我們經(jīng)常遇到上傳文件的需求煞肾,以前都是用到時再找資料咧织,但總是感覺對這塊不熟,最近翻資料學習了一下籍救,記錄一下习绢。
本文中涉及的知識點有:FileList對象,Blob對象蝙昙,F(xiàn)ile對象闪萄,URL對象、FormData對象等奇颠。
本文參考網(wǎng)道败去,總結而來。另外烈拒,強烈推薦網(wǎng)道圆裕,可以去網(wǎng)道的官方看看,是阮一峰大神發(fā)起的項目荆几,提供互聯(lián)網(wǎng)開發(fā)文檔吓妆,文檔非常全面易懂。
FileList 對象
FileList對象吨铸,是一個像數(shù)組的對象行拢,擁有l(wèi)ength屬性和item()方法,同時诞吱,它的每一項都是File對象舟奠。
input 標簽,將type設為file狐胎,之后得到的files屬性就是一個FileList對象鸭栖。
// html
<input type="file" accept="image/*" id="fileDiv" />
// js
var fileInput = document.getElementById('fileDiv');
var fileListObj = fileInput.files;
console.log(fileListObj instanceof FileList); // true
console.log(fileListObj.length); // 0
Blob 對象
blob 對象表示1個二進制文件的數(shù)據(jù)內(nèi)容。blob對象和arraybuffer區(qū)別是握巢,blob對象用于操作二進制文件,arraybuffer用于操作內(nèi)存松却。
blob 對象擁有2個屬性和1個方法暴浦,分別是size(單位是字節(jié))、type屬性和slice()方法晓锻。
File 對象
File 對象是一種特殊的Blob 對象歌焦。它在繼承了size、type屬性外砚哆,還同時有name独撇、lastModified、lastModifiedDate等幾個屬性。
FileList 對象中的每一項都是File 對象纷铣。
拿到File 對象之后就要進行操作卵史,下面是操作。
URL 對象
URL.createObjectURL(file) 允許為File 對象創(chuàng)建一個臨時鏈接搜立,
// 例如我們可以在選中了圖片之后以躯,展示到頁面上
// html
<input type="file" accept="image/*" id="fileDiv" onchange="getFile(this.files[0])" />
<img id="myimg" />
// js
function getFile(file){
var urlObj = URL.createObjectURL(file);
var myimg = document.getElementById('myimg');
myimg.src = urlObj;
console.log(urlObj);
}
/**
* 輸出如下:
* blob:http://127.0.0.1:8848/1410c491-27e2-47fa-8198-1d1ea4eece46
*/
FileReader 對象
FileReader 對象的屬性和方法比較多,屬性中比較重要的是result啄踊,方法中比較重要的是
- readAsText(file[,code]) 將文件讀取成為文本數(shù)據(jù)忧设,第二個參數(shù)默認采用utf-8編碼,返回到FileReader的result屬性中
- readAsArrayBuffer(file) 將文件讀取成為內(nèi)存數(shù)據(jù)颠通,返回到FileReader的result屬性中
- readAsBinaryString(file) 將文件讀取成為原始二進制數(shù)據(jù)址晕,返回到FileReader的result屬性中
- readAsDataURL(file) 將文件讀取成為base64字符串,返回到FileReader的result屬性中
// 例如顿锰,將文件讀取為base64數(shù)據(jù)谨垃,賦值給Img.src屬性
// html
<input type="file" accept="image/*" id="fileDiv" onchange="getFile(this.files[0])" />
<img id="myimg" />
// js
function getFile(file){
var myimg = document.getElementById('myimg');
var reader = new FileReader();
reader.onload = function(){
myimg.src = reader.result;
}
reader.readAsDataURL(file);
}
FileReader 對象的所有屬性和方法可以參考這里,這里就不再列出來了。
FormData 對象
在早期的互聯(lián)網(wǎng)時候撵儿,提交數(shù)據(jù)都是用表單乘客。表單提交數(shù)據(jù)有些缺陷,例如無法校驗表單數(shù)據(jù)淀歇,會刷新整個頁面等易核。隨著Ajax的興起,頁面表單提交數(shù)據(jù)慢慢退出歷史舞臺浪默,但有時上傳文件時我們偶爾會用到表單提交數(shù)據(jù)牡直。
在調(diào)用構造函數(shù)new FormData(form)構造formdata對象時需要傳入form節(jié)點,如果不傳入纳决,則默認構建空表單碰逸。如果傳入,則按照key=value的時候構建表單阔加。
// html
<form id="myform">
<input name="username" type="text" placeholder="請輸入用戶名" />
<br />
<br />
<input name="password" type="password" placeholder="請輸入密碼" />
<br />
<br />
<input name="age" type="number" placeholder="請輸入年齡" />
</form>
<br />
<input type="button" value="創(chuàng)建表單" id="mybtn" />
// js
var btn = document.getElementById('mybtn');
btn.onclick = function(){
var formNode = document.getElementById('myform');
var formdata = new FormData(formNode);
for(var pair of formdata.entries()){
console.log(pair[0] + ': ' + pair[1]);
}
}
可以看看效果圖
FormData 對象主要的方法有:
- get(key) 返回指定key的鍵值
- getAll(key) 返回指定key的所有鍵值饵史,如果有多個的話。(注意: set()方法會覆蓋同名鍵值對胜榔,append()方法則不會覆蓋)胳喷,返回值是1個數(shù)組
- set(key, value) 設置鍵值對
- delete(key) 刪除鍵值對
- append(key, value) 在formdata對象后邊添加鍵值對,如果第二個參數(shù)是文件夭织,還可以使用第三個參數(shù)吭露,表示文件名。
- has(key) 返回布爾值尊惰,表示是否具有該鍵名的鍵值對讲竿。
- keys() 返回一個遍歷器對象泥兰,用于for...of循環(huán)遍歷所有的鍵名。
- values() 返回一個遍歷器對象题禀,用于for...of循環(huán)遍歷所有的鍵值鞋诗。
- entries() 返回一個遍歷器對象,用于for...of循環(huán)遍歷所有的鍵值
cavas壓縮圖片
cavas壓縮圖片其實很簡單投剥,無非就是幾個步驟:
1师脂、選擇圖片,判斷圖片是否大于2M(用File對象的size進行判斷江锨,size的單位是字節(jié))吃警;
2、用FileReader對象讀取文件成base64,
3啄育、然后創(chuàng)建Image對象酌心,賦值src屬性,在Image對象加載完成的回調(diào)里創(chuàng)建cavas并繪制圖片(根據(jù)圖片是否大于2M動態(tài)調(diào)整畫布大小)挑豌;
4安券、將cavas轉成blob,拼在formdata中用ajax上傳氓英。
// 選擇圖片
$("#idcard_reverse_input").change(function (e) {
var loading = weui.loading('上傳中...');
// 判斷是否大于2M侯勉,大于2M需要壓縮圖片后再上傳
var result = e.target.files[0].size > 2*1024*1024;
var fileObj = e.target.files[0]; //上傳文件的對象
var reader = new FileReader();
reader.readAsDataURL(fileObj);
reader.onload = function(er) {
var image = new Image()
image.src = er.target.result;
image.onload = function() {
var canvas = document.createElement('canvas'),
context = canvas.getContext('2d'),
imageWidth = result?image.width * 0.1:image.width, //動態(tài)計算畫布大小
imageHeight = result?image.height * 0.1:image.height;
// 將畫布縮小為圖片的1/10,然后將圖片縮小畫入畫布中铝阐,之后到處畫布就能達到壓縮圖片的效果址貌。
canvas.width = imageWidth;
canvas.height = imageHeight;
context.drawImage(image, 0, 0, imageWidth, imageHeight);
canvas.toBlob(function(blob){
uploadReverse(blob,loading,true)
},'image/jpeg',0.8)
}
}
});
function uploadReverse(fileObj,loading,isReverse){
var time = new Date().getTime();
var str = 'code=G1&time=' + time;
// fileSecret是個全局變量,是個秘鑰
var apisign = md5(fileSecret + str);
// 構造表單數(shù)據(jù)
var formData = new FormData();
var imgName = isReverse ? 'reverse.png' : 'front.png'
formData.append("file",fileObj,imgName);
formData.append("apisign", apisign);
formData.append("time", time);
formData.append("code", 'G1');
$.ajax({
url : 'http://example.baidu.com/upload',
type:'post',
data: formData,
contentType: false,
processData: false,
success:function(res){
if(res.status != '1'){
weui.alert(res.info);
return ;
}
// 上傳成功
},
fail : function(){
weui.alert('上傳失敗,請重新選擇圖片上傳!')
},
complete:function(){
loading.hide()
}
})
}
總結
這篇文章到這里也就結束了徘键,這篇文章包含了一些瀏覽器中提供的對象练对,可以看到都是很簡單的內(nèi)容。