在利用vue做一些H5頁面時,或多或少會遇到有圖片上傳的操作,主要是運用html5里面的input[type=file]來實現,傳遞到后端的數據是以二進制的格式傳遞,所以上傳圖片的請求與普通的請求稍微有點差異,具體體現在傳遞數據的格式是FormData,FormData是一個構造函數,具體用法鏈接如下:
MDN:https://developer.mozilla.org/zh-CN/docs/Web/API/FormData
其次,由於圖片是以二進制方式上傳,所以需要修改下請求頭的Content-Type類型為“multipart/form-data”以支持二進制數據上傳。
在具體有以下幾部分的實現:
1、頁面端,利用H5的input[type=file]表單,進行圖片上傳,accept屬性可以設置接收文件的類型,具體有: .doc,.docx,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document
1 <input class="ele-hidden" type="file" accept="image/*" size="30" 2 ref="getPhoto" @change="uploadAvatar('getPhoto')">
2、選擇圖片確認后會觸發元素change事件,在input對象中,存在file屬性,file是一個數組,數組里面存儲的上傳文件的File對象,里面包含上傳文件的大小(size)、類型(type)、更改時間(lastModifiedDate)等。具體文檔可參考:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file
讀取圖片信息可以借助FileReader,解析成瀏覽器識別的格式,以實現圖片的預覽,FileReader構造函數文檔地址為:https://developer.mozilla.org/en-US/docs/Web/API/FileReader/FileReader,
實例代碼主要是為了解決移動端上傳圖片過大而進行了壓縮,壓縮后的圖片體積大概是壓縮前的十分之一,還是很可觀的。
uploadAvatar(node) {//圖片上傳
let $node = this.$refs[node];
let file = $node.files[0];//獲取當前選擇的照片
let formData = new FormData();
let _this = this;
if(!file) return;
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(e) {
let img = new Image();
img.onload = function () {
img.src = e.target.result;
let data = compress(img);
let blob = dataURItoBlob(data);
formData.append("photo", blob);
_this.submitModify(formData); //上傳方法
}
};
}
圖片解析和壓縮方法:
1 export function compress(img) { 2 let canvas = document.createElement("canvas"); 3 let ctx = canvas.getContext("2d"); 4 let initSize = img.src.length; 5 let width = img.width; 6 let height = img.height; 7 canvas.width = width; 8 canvas.height = height; 9 // 鋪底色 10 ctx.fillStyle = "#fff"; 11 ctx.fillRect(0, 0, canvas.width, canvas.height); 12 ctx.drawImage(img, 0, 0, width, height); 13 14 //進行最小壓縮 15 let ndata = canvas.toDataURL("image/jpeg", 0.1); 16 return ndata; 17 } 18 19 export function dataURItoBlob(base64Data) { 20 var byteString; 21 if (base64Data.split(",")[0].indexOf("base64") >= 0) 22 byteString = atob(base64Data.split(",")[1]); 23 else byteString = unescape(base64Data.split(",")[1]); 24 var mimeString = base64Data 25 .split(",")[0] 26 .split(":")[1] 27 .split(";")[0]; 28 var ia = new Uint8Array(byteString.length); 29 for (var i = 0; i < byteString.length; i++) { 30 ia[i] = byteString.charCodeAt(i); 31 } 32 return new Blob([ia], { type: mimeString }); 33 }
3、更改請求頭content-type類型
1 this.$axios.defaults.headers.post['Content-Type'] = 'multipart/form-data;charset=UTF-8';