Vue使用cube-ui的upload組件實(shí)現(xiàn)圖片壓縮

本文首發(fā)于:https://webug.io

簡(jiǎn)介

cube-ui是滴滴的一款基于Vue.js 實(shí)現(xiàn)的精致移動(dòng)端組件庫(kù)

官方文檔地址:https://didi.github.io/cube-ui/#/zh-CN

快速使用

我們?cè)谑褂胏ube-ui之前首先需要npm進(jìn)行安裝

npm install cube-ui --save

注意:此安裝部分只針對(duì)于 vue-cli < 3 的情況

安裝完成之后需要在main.js里面import一下

import Cube from 'cube-ui'
Vue.use(Cube);

接下來(lái)在頁(yè)面中就可以調(diào)用cube-ui的組件了!!蒿偎!

示例

<cube-upload
    ref="upload"
    :simultaneous-uploads="1"
    :max = "5"
    :auto="false"
    @files-added="filesAdded"
    @file-removed = "filesRemoved"
/>
  • simultaneous-uploads 上傳并發(fā)數(shù)
  • max 最多可選擇多少?gòu)?/li>
  • auto 是否自動(dòng)上傳
  • files-added 選擇完圖片回調(diào)方法
  • file-removed 刪除圖片回調(diào)方法

更多方法參數(shù)可見(jiàn):https://didi.github.io/cube-ui/#/zh-CN/docs/upload

具體方法實(shí)現(xiàn)
data(){
    return{
        imgList:[]
    }
}


// 這里的files是一個(gè)文件的數(shù)組
filesAdded(files) {
    let hasIgnore = false;
    const limitSize = 1 * 1024;
    // 最大5M
    const maxSize = 5 * 1024 * 1024;
    for (let i = 0; i< files.length; i++) {
      const file = files[i];
      // 如果選擇的圖片大小最大限制(這里為5M)則彈出提示
      if(file.size > maxSize){
        file.ignore = true;
        hasIgnore = true;
        break;
      }
      // 如果選擇的圖片大小大于1M則進(jìn)行圖片壓縮處理(Base64)
      if(file.size > limitSize){
        this.compressPic(file);
      }else{
        let reads= new FileReader();
        reads.readAsDataURL(file);
        let that = this;
        reads.onload = function(e) {
          var bdata = this.result;
          that.imgList.push(bdata)
        }
      }
    }
    hasIgnore && this.$createToast({
      type: 'warn',
      time: 1000,
      txt: '圖片最大支持5M'
    }).show()
},

// 圖片壓縮方法
compressPic(file){
    let reads= new FileReader();
    reads.readAsDataURL(file)
    // 注意這里this作用域的問(wèn)題
    let that = this;
    reads.onload = function(e) {
      var bdata = this.result;
      // 這里quality的范圍是(0-1)
      var quality = 0.1;
      var canvas = document.createElement("canvas");
      var ctx = canvas.getContext("2d");
      var img = new Image();
      img.src = bdata;
      img.onload =function() {
        var width = img.width;
        canvas.width = width;
        canvas.height = width * (img.height / img.width);
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
        let data = canvas.toDataURL("image/jpeg",quality);
        that.imgList.push(data)
      }
    };
  }

壓縮完成之后放入imgList數(shù)組中...

捋一下大概的邏輯焦履,其實(shí)非常簡(jiǎn)單:

  1. 前臺(tái)選擇完成圖片會(huì)進(jìn)入filesAdded方法回調(diào)中
  2. 在filesAdded主要做了兩個(gè)判斷:一是選擇圖片的大小不得超過(guò)5M,二則是如果選擇的圖片大于1M則進(jìn)行壓縮氓润,否則不進(jìn)行璧帝。
  3. 將壓縮過(guò)的base64代碼放入imgList數(shù)組中去

這個(gè)時(shí)候我們的數(shù)據(jù)已經(jīng)拿到了叔锐,接下來(lái)要做的就是上傳到后臺(tái)去黄痪。

submit(){
    const sendData = {
        imgList : this.imgList
    }
    this.remotePost('/upload', sendData, (rsp)=> {
         // 上傳成功后的業(yè)務(wù)邏輯
    }
}

后臺(tái)代碼

@RequestMapping("/upload", method=RequestMethod.POST)
@ResponseBody
public RspEntity imgUpload(HttpSession session, @RequestBody Map<String, Object> reqData) throws Exception {
    // 圖片列表
    List<String> imgList = (List<String>)reqData.get("imgList");
    
    // 通過(guò)for循環(huán)取出list中的base64代碼
    for(String imgBase64 : imgList){
        // 可通過(guò)base64轉(zhuǎn)file/byte[]等根據(jù)業(yè)務(wù)自行實(shí)現(xiàn)
    }
}

另外一種方式通過(guò)后臺(tái)進(jìn)行壓縮

data(){
    return{
        fileList: new FormData()
    }
}

filesAdded(files) {
    for (let k in files) {
      const file = files[k];
      this.existFile = file;
      this.fileList.append('files',file);
    }
}

submit(){
    this.remotePost('/upload', this.fileList, (rsp)=> {
         // 上傳成功后的業(yè)務(wù)邏輯
    }
}

這樣搞就是傳參就是file類(lèi)型的...

后臺(tái)代碼則需要進(jìn)行以下改造...

@RequestMapping("/upload", method=RequestMethod.POST)
@ResponseBody
public RspEntity imgUpload(HttpSession session, @RequestParam(value="files") MultipartFile[] files) throws Exception {
    for (int i = 0; i < files.length; i++) {
        MultipartFile file = files[i];
        String fileType = file.getContentType();
        if(StringUtils.isEmpty(fileType) || !fileType.matches("image.*")){
            logger.error("上傳圖片類(lèi)型錯(cuò)誤:" + fileType);
            rspEntity.setRspMsg("上傳圖片類(lèi)型錯(cuò)誤");
            rspEntity.setRspCode(AppConstants.MSG_STATUS_FAIL);
            return rspEntity;
        }
        if(file.getSize() > (long)(5 * 1024 * 1024)){
            logger.error("上傳圖片大小超過(guò)限制:" + file.getSize());
            rspEntity.setRspMsg("上傳圖片大小超過(guò)限制");
            rspEntity.setRspCode(AppConstants.MSG_STATUS_FAIL);
            return rspEntity;
        }
        String fileName = file.getOriginalFilename();
        String temp[] = fileName.split("\\.");
        if (temp.length < 2 || !temp[temp.length - 1].matches("(jpg|jpeg|png|JPG|JPEG|PNG)")) {
            logger.error("上傳圖片文件名錯(cuò)誤:" + fileName);
            rspEntity.setRspMsg("上傳圖片文件名錯(cuò)誤");
            rspEntity.setRspCode(AppConstants.MSG_STATUS_FAIL);
            return rspEntity;
        }
        byte[] imgCompress = CommUtil6442.compressPicForScale(file.getBytes(), 300, file.getOriginalFilename());
        // 具體根據(jù)業(yè)務(wù)實(shí)現(xiàn)
    }
}

這里是通過(guò)谷歌的一個(gè)圖片壓縮工具compressPicForScale紧帕,具體方法如下:

/**
     * 根據(jù)指定大小壓縮圖片
     *
     * @param imageBytes
     *            源圖片字節(jié)數(shù)組
     * @param desFileSize
     *            指定圖片大小,單位kb
     * @param imageId
     *            影像編號(hào)
     * @return 壓縮質(zhì)量后的圖片字節(jié)數(shù)組
     */
    public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize, String imageId) {
        if (imageBytes == null || imageBytes.length <= 0 || imageBytes.length < desFileSize * 1024) {
            return imageBytes;
        }
        long srcSize = imageBytes.length;
        double accuracy = getAccuracy(srcSize / 1024);
        try {
            while (imageBytes.length > desFileSize * 1024) {
                ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
                Thumbnails.of(inputStream).scale(accuracy).outputQuality(accuracy).toOutputStream(outputStream);
                imageBytes = outputStream.toByteArray();
            }
            logger.info("【圖片壓縮】imageId={} | 圖片原大小={}kb | 壓縮后大小={}kb", imageId, srcSize / 1024,
                    imageBytes.length / 1024);
        } catch (Exception e) {
            logger.error("【圖片壓縮】msg=圖片壓縮失敗!", e);
        }
        return imageBytes;
    }

    /**
     * 自動(dòng)調(diào)節(jié)精度(經(jīng)驗(yàn)數(shù)值)
     *
     * @param size
     *            源圖片大小
     * @return 圖片壓縮質(zhì)量比
     */
    private static double getAccuracy(long size) {
        double accuracy;
        if (size < 900) {
            accuracy = 0.85;
        } else if (size < 2047) {
            accuracy = 0.6;
        } else if (size < 3275) {
            accuracy = 0.44;
        } else {
            accuracy = 0.4;
        }
        return accuracy;
    }

使用之前需要在pom.xm里面引入桅打,如果不是maven項(xiàng)目則需要去網(wǎng)上搜索下載

<dependency>
    <groupId>net.coobird</groupId>
    <artifactId>thumbnailator</artifactId>
    <version>0.4.8</version>
</dependency>

遇到的坑

我們?cè)谑褂蒙蟼鞑寮臅r(shí)候是嗜,如果不是自動(dòng)上傳,則需要將action刪除掉挺尾,不能將其設(shè)置為:action="#"鹅搪,否則會(huì)請(qǐng)求兩次。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末遭铺,一起剝皮案震驚了整個(gè)濱河市涩嚣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌掂僵,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件顷歌,死亡現(xiàn)場(chǎng)離奇詭異锰蓬,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)眯漩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)芹扭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人赦抖,你說(shuō)我怎么就攤上這事舱卡。” “怎么了队萤?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵轮锥,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我要尔,道長(zhǎng)舍杜,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任赵辕,我火速辦了婚禮既绩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘还惠。我一直安慰自己饲握,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著救欧,像睡著了一般衰粹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上颜矿,一...
    開(kāi)封第一講書(shū)人閱讀 51,182評(píng)論 1 299
  • 那天寄猩,我揣著相機(jī)與錄音,去河邊找鬼骑疆。 笑死田篇,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的箍铭。 我是一名探鬼主播泊柬,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼诈火!你這毒婦竟也來(lái)了兽赁?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤冷守,失蹤者是張志新(化名)和其女友劉穎刀崖,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體拍摇,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡亮钦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了充活。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜂莉。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖混卵,靈堂內(nèi)的尸體忽然破棺而出映穗,到底是詐尸還是另有隱情,我是刑警寧澤幕随,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布蚁滋,位于F島的核電站,受9級(jí)特大地震影響合陵,放射性物質(zhì)發(fā)生泄漏枢赔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一拥知、第九天 我趴在偏房一處隱蔽的房頂上張望踏拜。 院中可真熱鬧,春花似錦低剔、人聲如沸速梗。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)姻锁。三九已至枕赵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間位隶,已是汗流浹背拷窜。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留涧黄,地道東北人篮昧。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像笋妥,于是被迫代替她去往敵國(guó)和親懊昨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)春宣、插件酵颁、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,094評(píng)論 4 62
  • 風(fēng)停雨至盡黃昏,昔日故人寄鄉(xiāng)魂月帝。秋風(fēng)吹落俠客夢(mèng)躏惋,明晨相思淚滿巾。
    阿杜阿云閱讀 251評(píng)論 0 3
  • 這篇文章說(shuō)一個(gè)我學(xué)習(xí)《薛兆豐的經(jīng)濟(jì)學(xué)課》給我感觸很大的一個(gè)觀念嚷辅,那就是一個(gè)人的現(xiàn)值其掂,是他未來(lái)可帶來(lái)收入的總和。 剛...
    師照照閱讀 311評(píng)論 0 0
  • 文人相輕深寥,出自三國(guó)?魏?曹丕《典論?論文》:“文人相輕攘乒,自古而然”,意指文人之間互相看不起惋鹅。 文人為何會(huì)相輕则酝?因?yàn)?..
    金錯(cuò)刀618閱讀 1,149評(píng)論 4 19
  • 從來(lái)沒(méi)有好好過(guò)母親節(jié),今天收到意外的驚喜闰集,紀(jì)念沽讹。途徑月峰寺,看見(jiàn)一個(gè)不停地算卦搖著竹簽的女人武鲁。凡塵中的難題爽雄,難為菩...
    夏洛的后花園閱讀 249評(píng)論 0 1