使用js在layui中實(shí)現(xiàn)上傳圖片壓縮
一、關(guān)于js上傳圖片壓縮的方法,百度有很多種方法,這里我參考修改了一下
function photoCompress(file, w, objDiv) { var ready = new FileReader(); /*開(kāi)始讀取指定的Blob對(duì)象或File對(duì)象中的內(nèi)容. 當(dāng)讀取操作完成時(shí),readyState屬性的值會(huì)成為DONE,如果設(shè)置了onloadend事件處理程序,則調(diào)用之.同時(shí),result屬性中將包含一個(gè)data: URL格式的字符串以表示所讀取文件的內(nèi)容.*/ ready.readAsDataURL(file); ready.onload = function() { var re = this.result; canvasDataURL(re, w, objDiv); } }; function canvasDataURL(path, obj, callback) { var img = new Image(); img.src = path; img.onload = function() { var that = this; // 默認(rèn)按比例壓縮 var w = that.width, h = that.height, scale = w / h; w = obj.width || w; h = obj.height || (w / scale); var quality = 0.5; // 默認(rèn)圖片質(zhì)量為0.7 //生成canvas var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); // 創(chuàng)建屬性節(jié)點(diǎn) var anw = document.createAttribute("width"); anw.nodeValue = w; var anh = document.createAttribute("height"); anh.nodeValue = h; canvas.setAttributeNode(anw); canvas.setAttributeNode(anh); ctx.drawImage(that, 0, 0, w, h); // 圖像質(zhì)量 if(obj.quality && obj.quality <= 1 && obj.quality > 0) { quality = obj.quality; } // quality值越小,所繪制出的圖像越模糊 var base64 = canvas.toDataURL('image/jpeg', quality); // 回調(diào)函數(shù)返回base64的值 callback(base64); } } function convertBase64UrlToBlob(urlData) { var arr = urlData.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while(n--) { u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], { type: mime }); }
以上是壓縮圖片的方法,核心是將圖片放入canvas內(nèi),再用canvas.toDataURL方法進(jìn)行壓縮,最后生成一個(gè)Blob對(duì)象。
注:因?yàn)闋砍兜絚anvas,所以低版本瀏覽器應(yīng)該是不支持的吧(有待考證)
二、圖片壓縮的方法有了,怎么使用呢?怎么上傳到后臺(tái)呢?往下看!
html部分:
<form action="file/uploadDoc" enctype="multipart/form-data" method="post" id="form"> <input type="file" id="file" name="file" /> <input type="submit" value="上傳" /> </form>
js部分:
$("#file").change(function() { var formData = new formData("form"); var file = this.files[0]; photoCompress(file, { quality: 0.5, }, function(base64Codes) { var bl = convertBase64UrlToBlob(base64Codes); formData.set("file", bl, file.name); }); });
當(dāng)選擇文件以后,使用photoCompress方法對(duì)上傳的圖片進(jìn)行壓縮,photoCompress方法的第二個(gè)參數(shù)還可以傳入長(zhǎng)寬等參數(shù),具體可以看photoCompress這個(gè)方法,quality是用來(lái)設(shè)置壓縮后圖片質(zhì)量的,越小質(zhì)量越差,表現(xiàn)出來(lái)就是圖片越模糊,但是相應(yīng)的體積就越小。
最后使用formData.set(key,value,name)方法,將現(xiàn)有的name為file的表單元素的值改變。這個(gè)方法有三個(gè)參數(shù),第一個(gè)是key值,也就是表單里對(duì)應(yīng)的元素的name值(如果不存在會(huì)自行添加),第二個(gè)值是value值,第三個(gè)是選填的值,如果第二個(gè)值為blob對(duì)象或者file對(duì)象,則第三個(gè)值表示文件名。
當(dāng)然,如果你不想用form表單提交,你也可以用ajax提交的方法:
html:
<form enctype="multipart/form-data" method="post" id="form"> <input type="file" id="file" name="file" /> <input type="button" value="上傳" id="uploadBtn"/> </form>
有些許的變化,form沒(méi)有了action,上傳的按鈕type改為了button
js部分給按鈕添加一個(gè)點(diǎn)擊事件,其他也沒(méi)有變化,不做過(guò)多贅述:
$("#uploadBtn").click(function () { var formData = new formData("form"); $.ajax({ type:"post", url:"", async:true, data:formData, success:function (data) { }, error:function (e) { } }); });
三、結(jié)合layui踩的一些坑,以及最終的解決方法。
先看html部分:
<button type="button" class="layui-btn" id="upImg">上傳圖片</button> <div id="img_list"> </div> <input type="button" id = "btnHide" class="none">
就是這么簡(jiǎn)單。為什么要再寫(xiě)一個(gè)隱藏的按鈕,之后解釋。
js部分:
layui.use('upload', function() { var upload = layui.upload; var uploadInst = upload.render({ elem: '#upImg', url: '/upload/', auto: false, bindAction: "#btnHide", choose: function(obj) { var files = obj.pushFile(); var index, file, indexArr = []; for(index in files) { indexArr.push(index); }; var iaLen = indexArr.length; file = files[indexArr[iaLen - 1]]; for(var i = 0; i < iaLen - 1; i++) { delete files[indexArr[i]]; } try { if(file.size > 200 * 1024) { delete files[index]; photoCompress(file, { quality: 0.5, }, function(base64Codes) { var bl = convertBase64UrlToBlob(base64Codes); obj.resetFile(index, bl, file.name); $("#btnHide").trigger("click"); }); } else { $("#btnHide").trigger("click"); } } catch(e) { $("#btnHide").trigger("click"); } }, done: function(res) { //這里把后臺(tái)返回的數(shù)據(jù)進(jìn)行操作,展示上傳完成的圖片,具體數(shù)據(jù)格式參考layui的API }, error: function() { } }); });
原理:在選擇照片之后,獲取文件,轉(zhuǎn)換為blob對(duì)象,使用resetFile方法對(duì)文件列隊(duì)里的文件進(jìn)行重新設(shè)置,然后再觸發(fā)上傳事件。
踩的坑:
1、resetFile這個(gè)方法是layui 2.3.0 新增的,所以首先要確保layui的版本是最新的。
2、我把a(bǔ)uto設(shè)置為false,點(diǎn)擊btnHide時(shí)觸發(fā)上傳,我也試過(guò)自動(dòng)上傳,自動(dòng)上傳的話,這些操作的代碼就要寫(xiě)在before方法中(具體看layui的API),然而我發(fā)現(xiàn)自動(dòng)上傳修改文件列隊(duì)的方法總是在上傳成功之后才調(diào)用,這就導(dǎo)致實(shí)際上傳的圖片其實(shí)沒(méi)有壓縮,至于為什么是這個(gè)執(zhí)行順序我隱約覺(jué)得是不是圖片轉(zhuǎn)碼,放入canvas的時(shí)候耽誤了……具體原因我不明白,所以我用手動(dòng)上傳,確認(rèn)修改了文件列隊(duì),再手動(dòng)觸發(fā)上傳。
3、關(guān)于文件列隊(duì),多次上傳文件,文件列隊(duì)也就是obj.pushFile()返回的是多個(gè)文件的對(duì)象,而且這些文件對(duì)象的key還是一串隨機(jī)數(shù)……所以我的思路是上傳一次,就用delete方法刪除隊(duì)列中已上傳過(guò)的文件。至于為什么不直接全部清空,因?yàn)榭紤]到不需要壓縮的情況,如果全部清空,不壓縮,就沒(méi)有執(zhí)行resetFile方法,文件列隊(duì)里就沒(méi)有文件,會(huì)報(bào)錯(cuò)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
小程序?qū)崿F(xiàn)簡(jiǎn)單的計(jì)算器
這篇文章主要為大家詳細(xì)介紹了小程序?qū)崿F(xiàn)簡(jiǎn)單的計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07javascript中parseInt()函數(shù)的定義和用法分析
這篇文章主要介紹了javascript中parseInt()函數(shù)的定義和用法,較為詳細(xì)的分析了parseInt()函數(shù)的定義及具體用法,以及參數(shù)使用時(shí)的注意事項(xiàng),需要的朋友可以參考下2014-12-12js實(shí)現(xiàn)時(shí)間日期校驗(yàn)
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)時(shí)間日期校驗(yàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05BooStrap對(duì)導(dǎo)航條的改造實(shí)踐小結(jié)
這篇文章主要介紹了BooStrap對(duì)導(dǎo)航條的改造實(shí)踐小結(jié)的相關(guān)資料,本文分步驟介紹的非常詳細(xì),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09淺析Js中的單引號(hào)與雙引號(hào)問(wèn)題
本文是對(duì)Js中單引號(hào)與雙引號(hào)的使用進(jìn)行了總結(jié)介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-11-11js實(shí)現(xiàn)卡片式項(xiàng)目管理界面UI設(shè)計(jì)效果
這篇文章主要介紹了js實(shí)現(xiàn)卡片式項(xiàng)目管理界面UI設(shè)計(jì)效果,該UI設(shè)計(jì)中,將各個(gè)項(xiàng)目以卡片的方式堆疊排列在屏幕上,當(dāng)點(diǎn)擊了其中的某個(gè)項(xiàng)目的時(shí)候,該項(xiàng)目圖片會(huì)全屏放大,向下滾動(dòng)鼠標(biāo)可以看到該項(xiàng)目的介紹信息,需要的朋友可以參考下2015-12-12基于JavaScript+HTML編寫(xiě)一個(gè)日期選擇插件
在現(xiàn)代Web應(yīng)用程序中,日期選擇器是一個(gè)非常常見(jiàn)的組件,用戶(hù)可以使用它來(lái)選擇特定的日期,在本篇文章中,我們將使用JavaScript和HTML來(lái)創(chuàng)建一個(gè)簡(jiǎn)單但功能強(qiáng)大的日期選擇插件,這個(gè)日期選擇插件是比較考驗(yàn)Js基本功的,需要的朋友可以參考下2023-10-10JS學(xué)習(xí)筆記之原型鏈和利用原型實(shí)現(xiàn)繼承詳解
這篇文章主要介紹了JS學(xué)習(xí)筆記之原型鏈和利用原型實(shí)現(xiàn)繼承,結(jié)合實(shí)例形式詳細(xì)分析了javascript原型鏈以及利用原型實(shí)現(xiàn)繼承的相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2019-05-05javascript開(kāi)發(fā)隨筆一 preventDefault的必要
給a做按鈕的click事件加preventDefault阻止瀏覽器的默認(rèn)行為貌似是印象中必須的事情2011-11-11