input file 實現上傳預覽圖片,以base64上傳,相容IE8+,firefox,chrome
阿新 • • 發佈:2019-01-07
前言
最近在公司開發一個專案,其中涉及到一個公能,主要是上傳一些小圖片,而且在網站上需要大量引用這個小圖片的,對於上傳一些小的頭像等。一開始覺得直接上傳就好了,但是發現這樣子的話,一個小圖片就會發送一個http請求資源,大量的小圖片的請求資源的話,會造成伺服器資源的負擔。而且我希望在使用者頭像上傳也可以不直接上傳image,以其他的方式上傳,可以將影象的資訊儲存在資料庫中,這樣子對於小圖片還是有好處的。經過了幾天的認真思考的查詢資料,自己寫了一個基於jquery實現的小外掛。就可以簡單的實現了小圖片的以base64的DATA URL 的協議上傳。
基本功能
1、基於外掛,可以自定義樣式,預覽框的大小
2、可以設定上傳圖片的型別,圖片的大小(建議100kb以內)
3、相容IE8+,firefox,chrom
4、以DAT URL協議實現圖片上傳前預覽,包括圖片的實際大小
5、返回上傳成功或者失敗的資訊
程式碼
previewUpload.js外掛程式碼:
上面的程式碼裡面有一些可能一下子無法理解,建議查詢一下資料。;(function($){ $.fn.previewUpload=function(options){ /** *預設選項配置 * */ var defaults={ //預覽框的樣色設定 'preview':{ 'border':'1px dashed', 'width':200,//必須int 'height':250,//必須int }, //上傳操作框樣式,預設為空,不做設定 'uploadImage':{}, //選擇圖片的按鈕樣式 'btnCss':{ 'display':'inline-block', 'line-height':'28px', 'font-size':'14px', 'text-align':'center', 'border':'1px solid #d0d0d5', 'border-radius':'4px', 'padding':'0 15px', 'min-width':'40px', 'background-color':'#fff', 'background-repeat':'no-repeat', 'background-position':'center', '-webkit-transition':'border-color .15s, background-color .15s', 'transition':' border-color .15s, background-color .15s', 'outline':'0 none', 'cursor':'pointer', 'overflow':'visible', 'border':'1px solid #00a5e0', 'background-color':'#00a5e0', 'color':'#fff', 'float':'left', }, //input file的樣式 'inputCss':{ 'position':'absolute', 'clip':'rect(0 0 0 0)', }, //彈出框選擇檔案的型別 'imageType':null, //設定圖片的大小,int 'imgSize':100, // 允許上傳的圖片格式 'typeAllow':'jpeg,jpg,png,gif', // 定義選擇檔案時,彈出框檔案顯示型別,預設是所有圖片 'acceptType':'image/*', //讀取base64編碼的圖片資料 'imgblod':null, // ajax非同步提交的資料的url 'url':null, // 從php返回html元素的最外層id /** *eg:<span id="resinfo"><font color=green>上傳成功</font></span> */ 'infoid':'resinfo', //設定返回資訊在頁面顯示的實際時間 'statTime':2000 } /** *繼承覆蓋預設配置 * */ var config=$.extend(defaults,options); config.sizeWarming='圖片太大,請選擇小於'+config.imgSize+'kb的圖片'; config.typeWarming='您上傳的圖片格式不正確,請重新選擇!'; config.browerWarming='瀏覽器版本太低'; /** *例項化物件this *將this賦值全域性的變數 */ var previewUploadDiv=$(this); /** *動態建立html元素 * */ var previewImage,uploadImage,imgTips; previewImage='<div class="previewImage" id="localImag"><img src="" id="preview"></div>'; uploadImage='<div class="uploadImage" style="margin-top:5px;">\ <label class="btn-select-img" for="img" >選擇圖片</label>\ <form id="imgform" method="post" action='+config.url+'>\ <input type="file" id="img" name="myimg">\ </form>\ <button class="btn btn-sm btn-info btn-upload-img" style="margin-left:20px;">上傳</button>\ <span class="imgsizespan"></span>\ </div>'; imgTips='<div class="imgTips"style="float:left">小於'+config.imgSize+'kb的'+config.typeAllow+'</div>'; /** *新增append */ previewUploadDiv.append(previewImage+uploadImage+imgTips); /** *設定樣式 * */ //預覽框樣式 previewUploadDiv.find('div.previewImage').css(config.preview); //上傳操作按鈕框上傳圖片按鈕樣式的樣式 previewUploadDiv.find('div.uploadImage').css(config.uploadImage); /**上傳圖片按鈕樣式 *滑鼠移動樣式 * */ previewUploadDiv.find('div.uploadImage label.btn-select-img').css(config.btnCss).mouseover(function(){ $(this).css({ 'background-color':'#00b4f5', 'border-color': '#00b4f5', 'color':'#fff' }); }).mouseout(function(){ $(this).css(config.btnCss); }); /**input file的框的樣式,主要是將該框隱藏透明掉 *同時指定瀏覽器接受的檔案型別,即選擇檔案彈出框的符合的檔案 * */ previewUploadDiv.find('input#img').css(config.inputCss).attr('accept',config.acceptType); /** *圖片預覽函式 * */ function setImagePreview(){ //獲取圖片物件 var imgObj=document.getElementById("img"); // 獲取預覽框物件 var imgObjPreview=document.getElementById("preview"); //判斷獲取的物件是否存在,chrom和firefox if(imgObj.files && imgObj.files[0]){ // 檢查大小和格式 var valid=checkSize(imgObj); if(valid){ //火狐下,直接設img屬性 imgObjPreview.style.display = 'block'; //火狐下,width,height要有單位'px' imgObjPreview.style.width = (config.preview.width-2)+'px'; imgObjPreview.style.height = (config.preview.height-2)+'px'; // imgObjPreview.src = docObj.files[0].getAsDataURL(imgObj.files[0]); //判斷瀏覽器的核心類別 var URL = window.URL || window.webkitURL; var objURL=URL.createObjectURL(imgObj.files[0]); //html5中的FileReader,將讀取圖片以base64的編碼資料 var reader = new FileReader(); //DATA URL 協議讀取base64編碼資料 // 格式:data:image/gif;base64,...... reader.readAsDataURL(imgObj.files[0]); //讀取資料完成,觸發一次事件函式 if(imgObjPreview.src = objURL){ /**每次呼叫createObjectURL的時候,一個新的URL物件就被建立了. *即使你已經為同一個檔案建立過一個URL. *如果你不再需要這個物件,要釋放它,需要使用URL.revokeObjectURL()方法. *當頁面被關閉,瀏覽器會自動釋放它,但是為了最佳效能和記憶體使用,當確保不再用得到它的時候,就應該釋放它. */ //等圖片載入完畢,再釋放記憶體 imgObjPreview.onload=function(){ URL.revokeObjectURL(objURL); } //讀取完圖片資料觸發時間執行 reader.onload = function(){ // 將讀取的base64資料賦值配置的全域性變數 config.imgblod=this.result; } }else{ reader.onload = function(){ // 將讀取的base64資料賦值配置的全域性變數 config.imgblod=this.result; imgObjPreview.src=this.result; } } }else{ return false; } }else{ //IE下,使用濾鏡 imgObj.select(); imgObj.blur(); //獲取文字內容值,在IE中input type=file 選擇檔案之後input顯示的是檔案在本地的路徑 var imgSrc = document.selection.createRange().text; var localImagId = document.getElementById("localImag"); //必須設定初始大小 localImagId.style.width =config.preview.width-2; localImagId.style.height =config.preview.height-2; //判斷格式 var imgType=imgSrc.split('.')[1]; if(config.typeAllow.indexOf(imgType)==-1){ // config.ievolid=0; alert(config.typeWarming); return false; } //獲取圖片大小 var img=new Image(); img.src=imgSrc; // 圖片載入完畢執行 img.onload=function(e){ var imgSize=Math.ceil(img.fileSize/1024); if(imgSize>config.imgSize){ img=null; alert(config.sizeWarming); return false; }else{ //將圖片顯示在預覽框 try{ localImagId.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale)"; localImagId.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = imgSrc; previewUploadDiv.find('span.imgsizespan').text(imgSize+'kb'); } catch(e) { alert(config.typeWarming); return false; } imgObjPreview.style.display ='none'; document.selection.empty(); return ; } } } return true; } /** *限制上傳圖片的大小和格式 *firefox和chrome */ function checkSize(imgObj){ var imgSize,imgType; if(imgObj.files && imgObj.files[0]){ // 單位位元組->kb imgSize=Math.ceil(imgObj.files[0]['size']/1024); //圖片型別 imgType=imgObj.files[0]['type'].split('/')[1]; // 大小比較 if(imgSize>config.imgSize){ alert(config.sizeWarming); return false; } //判斷型別 if(config.typeAllow.indexOf(imgType)==-1){ alert(config.typeWarming); return false; } previewUploadDiv.find('span.imgsizespan').text(imgSize+'kb'); return true; }else{ return true; } } /** *ajax非同步將資料post服務端 * */ function ajaxpost(){ previewUploadDiv.find('button.btn-upload-img').text('正在儲存'); //支援html5的瀏覽器,IE9+ if(config.imgblod){ /** *ajax非同步提交資料 * */ $.post(config.url,{'base64Data':config.imgblod,'type':'base64'},function(data){ if(data){ previewUploadDiv.find('button.btn-upload-img').text('上傳'); previewUploadDiv.find('span.imgsizespan').html(data); //啟動一個非同步定時器 setTimeout(function(){ previewUploadDiv.find('span.imgsizespan').empty(); },config.statTime); } }); /**IE8以下的瀏覽器 *只能將圖片上傳,再進行base641編碼 * */ }else{ //先移除iframe previewUploadDiv.find('iframe#uploadiframe').remove(); //動態建立form表單上傳屬性 previewUploadDiv.find('form#imgform').attr('enctype','multipart/form-data').attr("encoding", "multipart/form-data").attr('target','uploadiframe'); var iframeDiv = document.createElement('div'); iframeDiv.className='iframeDiv'; iframeDiv.innerHTML='<iframe id="uploadiframe" name="uploadiframe" style="display:none"></iframe>'; previewUploadDiv.append(iframeDiv); //立即執行回撥函式 (function(callback){ //表單提交上傳 previewUploadDiv.find('form#imgform').submit(); //setInterval() 方法返回的id控制代碼 config.timeid=setInterval(callback,200); })(function(){ //ie特有document.all if(document.all){ var content=document.getElementById('uploadiframe').contentDocument.getElementById(config.infoid).innerHTML; if(content){ previewUploadDiv.find('button.btn-upload-img').text('上傳'); previewUploadDiv.find('span.imgsizespan').html(content); //啟動一個非同步定時器 setTimeout(function(){ previewUploadDiv.find('span.imgsizespan').empty(); },config.statTime); //關閉setInterval()迴圈函式 window.clearInterval(config.timeid); } } }); } } /** *監聽input file的檔案圖片是否改變 * */ // juqery1.8低版本存在live(),jquery1.9+移除live(),用on()函式 if(previewUploadDiv.find('input#img').live){ previewUploadDiv.find('input#img').live('change',setImagePreview); }else{ previewUploadDiv.find('input#img').on('change',setImagePreview); } /** *監聽是否上傳 * */ if(previewUploadDiv.find('button.btn-upload-img').live){ previewUploadDiv.find('button.btn-upload-img').live('click',ajaxpost); }else{ previewUploadDiv.find('button.btn-upload-img').on('click',ajaxpost); } } })(jQuery);
html的程式碼:首先引入boostrap.min.css和jquery.js和上面的previewUpload.js檔案
可以看到html,用法很簡單,例項化一個jquery的物件即可,下面的自定義配置需要根據previewUpload.js的defaults的配置的key對應配置,就可以設定自己的需要引數。<head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>By:DragonDean</title> <link rel="stylesheet" type="text/css" href="bootstrap.min.css"> <script type="text/javascript" src="jquery-1.11.0.min.js"></script> <script type="text/javascript" src="previewUpload.js"></script> </head> <body> <div class="main" style="margin:0 auto;width:230px;height:350px;border:1px solid;padding:5px;" > </div> </body> </html> <script type="text/javascript"> $('div.main').previewUpload({ //預覽框的樣色設定 'preview':{ 'margin':'0 auto', 'border':'1px dashed', 'width':220,//必須int 'height':250,//必須int }, //彈出框選擇檔案的型別 'url':'test.php', 'imgSize':20000 }); </script>
php程式碼
<?php
header('Content-type:text/html;charset=utf-8');
/**
*firefox,chrom IE9+
*post過來的已經是base64字元編碼
*/
if(isset($_POST['type']) && $_POST['type']!=''){
$base64_image_content=$_POST['base64Data'];
/**
*do something
*/
}
/**
*IE8以下版本的只能上傳圖片,再用php編碼base64
*/
else{
if(is_uploaded_file($_FILES['myimg']['tmp_name'])){
$image_info = getimagesize($_FILES['myimg']['tmp_name']);
$base64_image_content = "data:{$image_info['mime']};base64," . chunk_split(base64_encode(file_get_contents($_FILES['myimg']['tmp_name'])));
/**
*do something
*/
}
}
// 返回
if($base64_image_content){
echo '<span id="resinfo"><font color=green>上傳成功</font></span>';
}else{
echo '<span id="resinfo"><font color=red>上傳失敗</font></span>';
}
?>
php服務端就簡單點,我這裡直接獲取post的資料就直接返回了,還需要做一下型別的判斷和大小的判斷,最後也可以將base64資料儲存在資料庫裡,可以繼續拓展。
效果圖
1、初始化的顯示
2、點選“選擇圖片”可以預覽,點選"上傳"可以上傳圖片,同時顯示圖片的大小