當項目中有圖片上傳功能時,便會產生服務器資源佔用問題,爲避免上傳圖片太大佔用太多空間,須要將圖片進行壓縮以後再存儲。php
圖片壓縮能夠經過前端或者後端均可以實現,這裏主要閒扯一下我使用的前端圖片壓縮:html
這裏介紹的js壓縮圖片的主要思想是:首先求出上傳的圖片大小,而後判斷是否大於限制的最大size,若大於,則將圖片進行壓縮。壓縮的過程就是,使用canvas將要壓縮的圖片畫出來。前端
首先使用FileReader對象讀取圖片,而後將圖片進行壓縮,將壓縮以後的對象轉換成blob對象(關於blob類型請參考http://blog.csdn.net/oscar999/article/details/36373183),最後將blob類型的文件放到formData中傳給後臺。html5
下面是壓縮插件代碼:canvas
/** * 這是基於html5的前端圖片工具,壓縮工具。 */ var ImageResizer=function(opts){ var settings={ resizeMode:"auto"//壓縮模式,總共有三種 auto,width,height auto表示自動根據最大的寬度及高度等比壓縮,width表示只根據寬度來判斷是否須要等比例壓縮,height相似。 ,dataSource:"" //數據源。數據源是指須要壓縮的數據源,有三種類型,image圖片元素,base64字符串,canvas對象,還有選擇文件時候的file對象。。。 ,dataSourceType:"image" //image base64 canvas ,maxWidth:500 //容許的最大寬度 ,maxHeight:500 //容許的最大高度。 ,onTmpImgGenerate:function(img){} //當中間圖片生成時候的執行方法。。這個時候請不要亂修改這圖片,不然會打亂壓縮後的結果。 ,success:function(resizeImgBase64,canvas){ }//壓縮成功後圖片的base64字符串數據。 }; var appData={}; $.extend(settings,opts); var innerTools={ getBase4FromImgFile:function(file,callBack){ var reader = new FileReader(); reader.onload = function(e) { var base64Img= e.target.result; if(callBack){ callBack(base64Img); } }; reader.readAsDataURL(file); }, //--處理數據源。。。。將全部數據源都處理成爲圖片對象,方便處理。 getImgFromDataSource:function(datasource,dataSourceType,callback){ var _me=this; var img1=new Image(); if(dataSourceType=="img"||dataSourceType=="image"){ img1.src=$(datasource).attr("src"); if(callback){ callback(img1); } } else if(dataSourceType=="base64"){ img1.src=datasource; if(callback){ callback(img1); } } else if(dataSourceType=="canvas"){ img1.src = datasource.toDataURL("image/jpeg"); if(callback){ callback(img1); } } else if(dataSourceType=="file"){ _me.getBase4FromImgFile(function(base64str){ img1.src=base64str; if(callback){ callback(img1); } }); } }, //計算圖片的須要壓縮的尺寸。固然,壓縮模式,壓縮限制直接從setting裏面取出來。 getResizeSizeFromImg:function(img){ var _img_info={ w:$(img)[0].naturalWidth, h:$(img)[0].naturalHeight }; var _resize_info={ w:0, h:0 }; if(_img_info.w <= settings.maxWidth && _img_info.h <= settings.maxHeight){ return _img_info; } if(settings.resizeMode=="auto"){ var _percent_scale=parseFloat(_img_info.w/_img_info.h); var _size1={ w:0, h:0 }; var _size_by_mw={ w:settings.maxWidth, h:parseInt(settings.maxWidth/_percent_scale) }; var _size_by_mh={ w:parseInt(settings.maxHeight*_percent_scale), h:settings.maxHeight }; if(_size_by_mw.h <= settings.maxHeight){ return _size_by_mw; } if(_size_by_mh.w <= settings.maxWidth){ return _size_by_mh; } return { w:settings.maxWidth, h:settings.maxHeight }; } if(settings.resizeMode=="width"){ if(_img_info.w<=settings.maxWidth){ return _img_info; } var _size_by_mw={ w:settings.maxWidth ,h:parseInt(settings.maxWidth/_percent_scale) }; return _size_by_mw; } if(settings.resizeMode=="height"){ if(_img_info.h<=settings.maxHeight){ return _img_info; } var _size_by_mh={ w:parseInt(settings.maxHeight*_percent_scale) ,h:settings.maxHeight }; return _size_by_mh; } }, //--將相關圖片對象畫到canvas裏面去。 drawToCanvas:function(img,theW,theH,realW,realH,callback){ var canvas = document.createElement("canvas"); canvas.width=theW; canvas.height=theH; var ctx = canvas.getContext('2d'); ctx.drawImage(img, 0,//sourceX, 0,//sourceY, realW,//sourceWidth, realH,//sourceHeight, 0,//destX, 0,//destY, theW,//destWidth, theH//destHeight ); //--獲取base64字符串及canvas對象傳給success函數。 var base64str=canvas.toDataURL("image/png"); if(callback){ callback(base64str,canvas); } } }; //--開始處理。 (function(){ innerTools.getImgFromDataSource(settings.dataSource,settings.dataSourceType,function(_tmp_img){ var __tmpImg=_tmp_img; settings.onTmpImgGenerate(_tmp_img); //--計算尺寸。 var _limitSizeInfo=innerTools.getResizeSizeFromImg(__tmpImg); var _img_info={ w:$(__tmpImg)[0].naturalWidth, h:$(__tmpImg)[0].naturalHeight }; innerTools.drawToCanvas(__tmpImg,_limitSizeInfo.w,_limitSizeInfo.h,_img_info.w,_img_info.h,function(base64str,canvas){ settings.success(base64str,canvas); }); }); })(); var returnObject={ }; return returnObject; }; function dataURLtoBlob(dataurl) { var arr = dataurl.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}); }
下面是調用壓縮插件的代碼:後端
var formData = new FormData(), oFile = $('#'+fileId)[0].files[0], imgSize = oFile.size; if(imgSize < 256 * 1024){ formData.append(fileId, oFile); uploadPic(formData, picNum); } else { // 圖片壓縮處理 var reader = new FileReader(), maxWidth = 400, maxHeight= 400, suffix = oFile.name.substring(oFile.name.lastIndexOf('.') + 1); if(imgSize > 2 * 1024 * 1024){ maxWidth = 800; maxHeight= 800; } reader.onload = function(e) { var base64Img= e.target.result; //--執行resize。 var _ir=ImageResizer({ resizeMode:"auto", dataSource:base64Img, dataSourceType:"base64", maxWidth:maxWidth, //容許的最大寬度 maxHeight:maxHeight, //容許的最大高度。 onTmpImgGenerate:function(img){ }, success:function(resizeImgBase64,canvas){ var blob = dataURLtoBlob(resizeImgBase64); formData.append(fileId, blob, oFile['name']); uploadPic(formData, picNum); } }); }; reader.readAsDataURL(oFile); }
在使用file控件時,有一個accpt屬性能夠在上傳文件的時候篩選文件類型,好比,只容許上傳圖片:服務器
<?php echo html::file('selectPic', "class='upload' accept='image/*'");?>