今天作商城上傳商品的的時候遇到一個需求,就是上傳圖片的時候須要經過多個上傳圖片域,上傳不一樣的圖片,之前由於項目進度很緊張,採起了一種應急措施:經過一個文件域上傳,以下圖: html
以前用的是dropzone來上傳圖片,今天研究了良久,發現dropzone很難實現這樣一個需求,因而換了一個上傳圖片插件:webuploader。 前端
webuploader是一款由百度前端研發部開發的很是優秀的上傳圖片插件,採用大文件分片併發上傳,支持經常使用圖片格式jpg,jpeg,gif,bmp,png預覽與壓縮,節省網絡數據傳輸,支持文件多選,類型過濾,拖拽(文件&文件夾),圖片粘貼功能等功能。官網地址:http://fex.baidu.com/webuploader/ java
以後咱們能夠經過官網的一些例子快速上手這個插件,當咱們經過官網的例子,能夠作出相似以下的效果: web
(圖片那些是我本身加的,先不要管),當咱們想要加入加入多個文件域的時候咱們因該怎麼作呢? api
<div id="uploader"> <div id="queueListindex"> <span>首頁圖(最多1張圖片)</span> <div id="dndArea" class="placeholder" style="margin-top: 20px"> <div id="filePicker"></div> <p>單次最多可選1張</p> </div> </div> <div id="queueListgalley"> <span>輪播圖(最多3張圖片)</span> <div id="dndArea1" class="placeholder" style="margin-top: 80px"> <div id="filePicker1"></div> <p>單次最多可選3張</p> </div> </div> <div id="queueListdescrip"> <span>詳情圖(最多4張圖片)</span> <div id="dndArea2" class="placeholder" style="margin-top: 80px"> <div id="filePicker3"></div> <p>單次最多可選4張</p> </div> </div><div class="statusBar" style="display:none;"> <div class="progress"> <span class="text">0%</span> <span class="percentage"></span> </div> <div class="info"></div> <div class="btns"> <div id="filePicker2"></div> </div> </div> <div class="uploadBtn am-btn am-btn-primary"><input type="submit" class="am-btn am-btn-primary" value="開始上傳"> </div>
</div>
在這裏咱們初始化了3個選擇圖片的佈局域(id爲queueListindex,queueListgalley,queueListdescrip),而且初始化了上傳商品的按鈕,以後咱們須要在咱們的js文件裏面初始化控件並激活選擇圖片按鈕 瀏覽器
var $wrap = $('#uploader'), // 圖片容器 $queueIndex = $('<ul class="filelist"></ul>') .appendTo($wrap.find('#queueListindex')), // 圖片容器 $queueGalley = $('<ul class="filelist"></ul>') .appendTo($wrap.find('#queueListgalley')), // 圖片容器 $queueDescrip = $('<ul class="filelist"></ul>') .appendTo($wrap.find('#queueListdescrip')), // 狀態欄,包括進度和控制按鈕 $statusBar = $wrap.find('.statusBar'), // 文件整體選擇信息。 $info = $statusBar.find('.info'), // 上傳按鈕 $upload = $wrap.find('.uploadBtn'), // 沒選擇文件以前的內容。 $placeHolderIndex = $wrap.find('#dndArea'), $placeHolderGalley = $wrap.find('#dndArea1'), $placeHolderaDescrip = $wrap.find('#dndArea2'),
uploader = WebUploader.create({ pick: { //選擇按鈕 id: '#filePicker1', label: '點擊選擇圖片', multiple: true }, formData: { //表單附帶的能夠寫在這,若是隻上傳圖片就能夠不要 uid: uid }, threads:1, //同一時間只容許一個圖片上傳 dnd: '#dndArea', paste: '#uploader', swf: contextPath + '/resources/js/webUploader/Uploader.swf', //改爲本身的Uploader.swf地址 chunked: false, chunkSize: 512 * 1024, duplicate:true, //是否容許重複的圖片上傳 server: contextPath + '/zhu/shelves', //接收表單的地址 runtimeOrder: 'flash', accept: { title: 'Images', extensions: 'gif,jpg,jpeg,bmp,png', mimeTypes: 'image/*' }, multiple: true, // 禁掉全局的拖拽功能。這樣不會出現圖片拖進頁面的時候,把圖片打開。 disableGlobalDnd: true, fileNumLimit: 15, fileSizeLimit: 20 * 1024 * 1024, // 200 M fileSingleSizeLimit: 10 * 1024 * 1024 // 50 M });
這裏咱們初始化了咱們的控件,而後咱們繼續添加咱們的剩下的上傳按鈕 服務器
uploader.addButton({ id: '#filePicker', innerHTML: '選擇文件' }); uploader.addButton({ id: '#filePicker3', innerHTML: '選擇文件' });
在這裏咱們能夠添加咱們的剩下的兩個按鈕,以後咱們的3個文件域就差很少出來了,以下圖: 網絡
在這個地方我遇到了一個問題,當我每次點擊上傳圖片的時候,我須要肯定我當前選定的這個文件域是那個文件域,可是當我用jq的on事件綁定咱們選擇文件按鈕的控件的時候,我本身綁定的on會失效,找了下緣由,因該是當我點擊選擇文件的時候會彈出上傳文件,兩個事件重複綁定形成的,因此我換了種思路,利用 併發
var mybutton;//標誌位 $('#filePicker1').on('mouseover', function () { mybutton = 1; }); $('#filePicker').on('mouseover', function () { mybutton = 0; }); $('#filePicker3').on('mouseover', function () { mybutton = 2; });
以後又有一個需求,咱們在不一樣文件域的圖片的最大數是不一樣的,例如:咱們的queueListindex域裏面就只容許有一張圖片 app
翻了下webuploder api文檔,有一個'beforeFileQueued'事件用於處理當咱們的文件加入上傳隊列以前的操做。
uploader.on('beforeFileQueued', function (file) { if (mybutton == 0) { fileCountIndex++; //首頁域的文件數量 if (fileCountIndex > 1) { return false; } } else if (mybutton == 1) { fileCountGalley++;//輪播域的文件數量 if (fileCountGalley > 3) { return false; } } else if (mybutton == 2) { fileCountDescrip++;//詳情域的文件數量 if (fileCountDescrip > 4) { return false; } } });
在這個事件裏面,咱們經過當前的文件域來判斷在當前這個文件域文件數達到最大值時則不能上傳圖片,若是不能,那麼返回false,不讓圖片加入咱們的隊列。
當咱們文件加入隊列後,咱們須要把加入隊列的文件顯示到咱們的頁面上,咱們能夠經過onFileQueued事件,處理在隊列裏面的圖片
uploader.onFileQueued = function (file) { if (mybutton == 0) { fileSizeIndex += file.size; if (fileCountIndex === 1) { $placeHolderIndex.addClass('element-invisible');//把咱們對應的上傳域隱藏,以後咱們會添加控件顯示咱們添加了的圖片。 $statusBar.show(); } } else if (mybutton == 1) { fileSizeGalley += file.size; if (fileCountGalley === 1) { $placeHolderGalley.addClass('element-invisible'); $statusBar.show(); } } else if (mybutton == 2) { fileSizeDescrip += file.size; if (fileCountDescrip === 1) { $placeHolderaDescrip.addClass('element-invisible'); $statusBar.show(); } } addFile(file); //添加文件 setState('ready'); //設置狀態,代碼沒貼出 updateTotalProgress();//更新進度,代碼沒貼出 };
function addFile(file) { var $li = $('<li id="' + file.id + '">' + '<p class="title">' + file.name + '</p>' + '<p class="imgWrap"></p>' + '<p class="progress"><span></span></p>' + '</li>'), //新建一個佈局用於存放咱們的圖片 $btns = $('<div class="file-panel">' + '<span class="cancel">刪除</span>' + '<span class="rotateRight">向右旋轉</span>' + '<span class="rotateLeft">向左旋轉</span></div>').appendTo($li), $prgress = $li.find('p.progress span'), $wrap = $li.find('p.imgWrap'), $info = $('<p class="error"></p>'), showError = function (code) { switch (code) { case 'exceed_size': text = '文件大小超出'; break; case 'interrupt': text = '上傳暫停'; break; default: text = '上傳失敗,請重試'; break; } $info.text(text).appendTo($li); }; var suffix = file.name.split('.')[file.name.split('.').length - 1]; //記錄文件後綴名 if (mybutton == 0) { file.name = "index" + i + "." + suffix;//給文件命名,根據前綴來區分是哪一類的圖片 $li.appendTo($queueIndex); } else if (mybutton == 1) { file.name = "galley" + i + "." + suffix; $li.appendTo($queueGalley); } else if (mybutton == 2) { file.name = "describe" + i + "." + suffix; $li.appendTo($queueDescrip); } i++; }
當咱們作到這一步的時候,其實已經能夠上傳圖片到咱們的服務器了,可是當咱們須要連同表單一塊兒上傳進入服務器的話咱們就須要uploadBeforeSend事件來處理:
uploader.on('uploadBeforeSend', function (obj, data) { //data.bbb="sadasd"; //alert(uid); data.uid = uid; data.goods_name = $("input[name='goods_name']").val(); data.type = $("input[name='type']").val(); data.price = $("input[name='price']").val(); data.goods_number = $("input[name='goods_number']").val(); mydiv = $('#my_select'); data.categoryId = $(mydiv.children('select')[mydiv.children('select').length - 1]).children('option:selected').val(); data.descri = $("input[name='descri']").val(); });
像這種格式,直接把data後面跟上參數名就能夠給參數賦值。
$upload.on('click', function () { uploader.upload(); });
再經過 uploader.upload() 來上傳咱們的表單,以後的話圖片和表單就能夠上傳進咱們的服務器了,以下圖:
在這裏尚未完,由於咱們的webuploder是採起分片上傳圖片的,每次只上傳一張圖片,不像dropzone同樣,一次上傳全部的圖片,因而乎就涉及到一個問題,之前的服務器端的代碼不能用了,因此我把服務器端的代碼改了一下,適應咱們的前端的需求。
在前端的話咱們須要每次上傳的時候添加個標識位:
var uid = 0;
以後咱們把uid上傳進服務器端
String myId = request.getParameter("uid"); if (myId.equals("0")){ //建立新的商品,並保存圖片 }else{ //把圖片保存進剛剛新建的商品裏面 }
當咱們服務器端收到第一張圖片時會自動的生成一條商品信息,以後咱們會返回咱們剛剛生成的商品的id給咱們的瀏覽器,上傳成功,瀏覽器接收後
uploader.on('uploadSuccess', function (file, response) { uid = response.text; });
咱們把返回的商品Id賦值給咱們的標誌位uid, 而後由於咱們的webuploder是分片上傳的,剛開始初始化時咱們須要把threads設置爲1,
threads: 1,
由於這樣咱們圖片會等一張傳完了後纔開始上傳第二張,因此咱們就把咱們返回的商品id上傳給了咱們的服務器,以後在服務器端判斷後把圖片存入對應的商品