圖片的上傳通常狀況下不須要上傳大致積的圖片,由於若是是用戶頭像或者是一些要求清晰度不是過高的場景上傳大致積圖片會很消耗資源,一個是上傳耗時比較長,同時也增長了存儲的開銷,當展現的時候也會消耗下載的帶寬,影響加載效率。要求用戶上傳的圖片以前壓縮圖片很影響用戶體驗,因此就增長了在前端進行圖片壓縮的需求。javascript
前端圖片壓縮的主要思路就是將圖片繪製到canvas中,而後經過canvas的toDataURL方法來控制圖片的質量,對圖片進行壓縮,另外一方面是對圖片進行寬高等比縮小來達到圖片壓縮的效果,下面來看一下代碼示例:前端
resizeMe(img,type, max_width, max_height) {
var canvas = document.createElement('canvas');
var width = img.width;
var height = img.height;
max_width = !isNaN(max_width)?max_width:0;
max_height = !isNaN(max_height)?max_height:0;
// 在這裏圖片是等比例縮放的,調用方法時填入圖片容許的最大寬度或者是最大的高度
//若是最大寬度爲0 則按照最大高度固定,寬度自適應的方式來實現
//若是是最大高度爲0,則按照最大的寬度來實現
if(max_width==0){
if (height > max_height) {
width = Math.round(width *= max_height / height);
height = max_height;
}
}
if(max_height==0){
if (width > max_width) {
height = Math.round(height *= max_width / width);
width = max_width;
}
}
canvas.width =width;
canvas.height = height;
var ctx = canvas.getContext("2d");
canvas.width =width;
canvas.height = height;
ctx.drawImage(img,0,0, width, height);
type = type === 'jpg'?"jpeg":type;
return canvas.toDataURL("image/"+type, 0.7);//這裏的0.7值的是圖片的質量
}
複製代碼
在上面的代碼中,咱們傳入的參數主要有image對象,圖片類型,圖片的最大寬度和最大高度。調用方法時填入圖片容許的最大寬度或者是最大的高度,進行等比繪製到canvas中,而後經過toDataURL來轉換成base64格式返回,此時的圖片就是壓縮事後的圖片。java
上面的示例說了圖片壓縮的過程,其中有一個參數是image對象,那麼這個image對象是如何來的呢。node
selectFileImage(el){
var reader = new FileReader();
var file = el.target.files[0]
var fileName = file.name;
var fileType = file.name.split(".")[1];
reader.readAsArrayBuffer(file);
reader.onload = (ev) => {
var blob = new Blob([ev.target['result']]);
window['URL'] = window['URL'] || window['webkitURL'];
var blobURL = window['URL'].createObjectURL(blob);
var image = new Image();
image.src = blobURL;
image.onload = (e) => {
var thumb = this.resizeMe(image,fileType, 400, 0);//得到的路徑是將圖片轉換成了base64
axios.post("http://127.0.0.1:3003/useasync/upload",{file:thumb,fileName:fileName}).then(res => {
if (res.data.code == 200) {
console.log(res)
} else {
console.log(res)
}
});
}
}
}
複製代碼
在這裏面我使用了一個FileReader對象,FileReader 對象容許Web應用程序異步讀取存儲在用戶計算機上的文件(或原始數據緩衝區)的內容,使用 File 或 Blob 對象指定要讀取的文件或數據。ios
當觸發input的onChange事件後,能夠讀取到input中的file文件,因而將此文件讀取到緩存當中,當讀取完成後,result屬性中保存的將是被讀取文件的ArrayBuffer數據對象。這裏咱們能夠看一下讀取完成後的這個ev究竟是個什麼東西 咱們能夠看到這裏面loaded和total都表示的是文件的總大小,重要的實際上是target和currentTarget,這兩個屬性實際上是同樣的,裏面包含了讀取的fileReader對象,裏面的result就是緩存中的數據了,咱們經過new 一個Blob對象,將其轉換爲Blob對象,而後就能夠經過url方法來將其轉換爲能夠放到img src中的連接形式了。此時建立image對象,並對其src進行賦值,當image加載完成後,就開始調用壓縮方法,傳入的image對象就是咱們剛纔生成的image對象。web
當壓縮完成後返回的數據就是base64的數據了,咱們就能夠經過ajax異步來進行上傳,在此我採用的是axios進行異步上傳,將內容及文件名做爲參數傳遞給後臺。ajax
在這我才用的示例爲nodejs搭建後臺來接收圖片,這裏咱們須要一個bodyParser模塊json
app.use(bodyParser.json({ limit:'5mb'}));//限制容許提交的大小
複製代碼
將大小限制爲5M之內,也就是說經過base64上傳的圖片大小必定要小於5M才能成功,這個參數咱們能夠隨意更改,按業務需求而定。canvas
router.post("/upload",function(req,res){
var imgData = req.body.file;
var fileName = req.body.fileName;
var base64Data = imgData.replace(/^data:image\/\w+;base64,/, "");
//var size = Buffer.byteLength(base64Data,'base64');
//var dataBuffer = Buffer.alloc(size,base64Data, 'base64');
var dataBuffer = Buffer.from(base64Data, 'base64');
fs.writeFile(process.cwd()+"/upload/"+fileName, dataBuffer, function(err) {
if(err){
res.json({success:false,errormsg:err});
}else{
res.send({success:true,msg:"保存成功!"});
}
});
})
複製代碼
接口中咱們經過Buffer來將base64轉換爲buffer,進而保存到服務器本地中,本示例採用的就是將圖片保存到服務器本地。如此經過將base64編碼圖片保存爲圖片就作完了。axios
因爲壓縮採用的是canvas,獲取文件等是經過FileReader 對象及Bolb對象,故此方法目前的兼容性最低爲IE10,還請酌情使用。
文章發表自:前端圖片壓縮及上傳