封裝一個簡易的上傳附件方法
之前做專案,總能碰到上傳附件的需求,不管是web端,還是移動端;當然,網上有很多第三方的外掛,比如基於vue的element-ui的上傳附件,但用第三方的外掛修改起來很費事,層層包裹;所以自己封裝了一個上傳附件的方法,自己寫的方法,用和修改起來是很爽的,哈哈
GitHub地址
ofollow,noindex">github.com/lirongrong/…
演示

功能
- 上傳附件分為圖片和非圖片兩種格式
- 上傳的附件會被編譯成base64位格式
- 對上傳的圖片進行壓縮處理
HTML
通過vue繫結change事件
<input type="file" multiple="multiple" v-on:change="chooseImage" placeholder="上傳圖片" /> 複製程式碼
JS
下面的大家應該都知道:chooseImage能獲取到上傳的附件資訊
chooseImage(e){ var files = e.target.files; } 複製程式碼
遍歷files,判斷上傳附件的大小格式等
var defaults = { folder: "default", size: 3, type: ['image', 'word', 'pdf', 'zip', 'rar', 'sheet', 'text','log','psd'], maxWidth: Number, //最大寬度 maxHeight: Number, //最大高度 success: false, beforeSend: false, }; for (var i = 0; i < files.length; i++) { var file = files[i]; //附件大於3M,被禁止 if (file.size > defaults.size * 1024 * 1024) { that.showToast("檔案【" + file.name + "】大於" + defaults.size + "M!"); return; } //不在上傳格式範圍內的,被禁止 var valiType = false; for (var i = 0; i < defaults.type.length; i++) { var item = defaults.type[i]; if (file.type.indexOf(item) >= 0) { valiType = true; break; } } if (!valiType) { that.showToast("上傳檔案型別不正確!"); return; } ... } 複製程式碼
接著用到了HTML5的FileReader方法:
FileReader 物件允許Web應用程式非同步讀取儲存在使用者計算機上的檔案(或原始資料緩衝區)的內容,使用 File 或 Blob 物件指定要讀取的檔案或資料。
接著上面for迴圈裡三個...的地方繼續寫,這裡需要住的地方是:
上傳的附件分為圖片和非圖片的型別,這樣分的目的是,上傳圖片的時候會壓縮圖片,以防圖片太寬或太高佔用伺服器空間
var reader = new FileReader(); var type = file.type.split('/')[0]; reader.readAsDataURL(file); reader.onloadstart = function () { //用以在上傳前加入一些事件或效果,如載入中...的動畫效果 that.loading = 'loading'; }; reader.onloadend = function(){ //刪除載入效果 that.loading = ''; //當附件格式不是圖片的時候 if(type != 'image') that.model.fileList.push(file); //當附件格式為圖片的時候 var dataURL = this.result; var imaged = new Image(); imaged.src = dataURL; imaged.onload = function () { var img = this; //利用canvas對圖片進行壓縮 var getImg = that.getBase64Image(img,{ maxWidth:1000, maxHeight:1000 }); that.model.imgList.push({ src:getImg.dataURL }) }; } 複製程式碼
所有的附件都在data model中,下面是頁面的繫結
<!--上傳除圖片外的其他附件--> <ul> <li class="flex flex_align_center" style="padding:6px 0;" v-for="(item,index) in model.fileList" :key="index"> <span class="flex_item">{{item.name}}</span> <a title="刪除" class="ml10" @click="deleteFile(index)">刪除</a> </li> </ul> <!--上傳圖片--> <ul id="preview" class="flex flex_wrap"> <li v-for="(item,index) in model.imgList" :key="index" style="flex-basis: 20%;" class="pr"> <img :src="item.src" alt=""/> <i class="iconfont icon-shanchu pa" @click="deleteImg(index)"></i> </li> </ul> <div>{{loading}}</div> 複製程式碼
大家可能注意到了壓縮圖片的getBase64Image方法,這是我自己封裝的一個方法,通過定義最大寬度和最大高度來等比壓縮圖片,不要擔心圖片會變形,用到canvas來壓縮圖片,下面是封裝的方法
細心的朋友也許會發現:演示圖片最後我上傳的圖片畫素為3543 * 5315,上傳之後圖片大小等比壓縮成667 * 1000,因為最大寬度和最大高度我設定的是1000,所以相對應寬高會等比縮小
/** * 圖片檔案轉base64 */ getBase64Image:function(img,options){ var defaults = { maxWidth : Number, maxHeight : Number }; if(options != undefined && options != null){ defaults = $.extend(defaults,options) }; // 縮放圖片需要的canvas var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); // 圖片原始尺寸 var originWidth = img.width; var originHeight = img.height; // 最大尺寸限制,可通過國設定寬高來實現圖片壓縮程度 var maxWidth = defaults.maxWidth, maxHeight = defaults.maxHeight; // 目標尺寸 var targetWidth = originWidth, targetHeight = originHeight; // 圖片尺寸超過400x400的限制 if(originWidth > maxWidth || originHeight > maxHeight) { if(originWidth / originHeight > maxWidth / maxHeight) { // 更寬,按照寬度限定尺寸 targetWidth = maxWidth; targetHeight = Math.round(maxWidth * (originHeight / originWidth)); } else { targetHeight = maxHeight; targetWidth = Math.round(maxHeight * (originWidth / originHeight)); } } // canvas對圖片進行縮放 canvas.width = targetWidth; canvas.height = targetHeight; // 清除畫布 context.clearRect(0, 0, targetWidth, targetHeight); // 圖片壓縮 context.drawImage(img, 0, 0, targetWidth, targetHeight); /*第一個引數是建立的img物件;第二個引數是左上角座標,後面兩個是畫布區域寬高*/ //壓縮後的圖片base64 url /*canvas.toDataURL(mimeType, qualityArgument),mimeType 預設值是'image/jpeg'; * qualityArgument表示匯出的圖片質量,只要匯出為jpg和webp格式的時候此引數才有效果,預設值是0.92*/ dataURL = canvas.toDataURL('image/jpeg'); //回撥函式用以向資料庫提交資料 var base64 = dataURL.substr(dataURL.indexOf(",") + 1); return {dataURL,base64}; }, 複製程式碼
額外再補充一個提示方法
/** * 提示資訊 */ showToast : function (msg) { var objToast = "<div class='rr_toast'>" + msg + "</div>" $(document.body).append(objToast); setTimeout(function () { $('.rr_toast').remove(); }, 1000) } 複製程式碼