封裝一個簡易的上傳附件方法

RR?發表於2018-10-09

前言

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

GitHub地址

github.com/lirongrong/…

演示

封裝一個簡易的上傳附件方法

功能

  1. 上傳附件分為圖片和非圖片兩種格式
  2. 上傳的附件會被編譯成base64位格式
  3. 對上傳的圖片進行壓縮處理

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)
}
複製程式碼

待優化

  1. 暫不支援多圖一起上傳,需改進
  2. 上傳loading效果待優化,現在只是簡單的loading文字展示隱藏
  3. 圖片預覽
  4. 非圖片附件預覽

總結

上面的完整程式碼在github上,大家可以直接下載執行,有誤的地方歡迎大家指正。

相關文章