最近在做項目中用到了plupload插件,這里簡單記錄下個人在項目中遇到的一些坑及解決方法。
1.關於兼容性
plupload可以支持到ie6,由於考慮到兼容性,所以選擇了plupload,會根據html5,flash,silverlight,html4逐層退化
2.browse_button點擊失效
可能有些用戶遇到過這種情況,我也遇到了,我的情況是,browse_button的container隱藏了,導致runtime為flash出現報錯,所以確保你的container可見
3.多個browse_button問題
產品提了這個需求,用戶添加了一些圖片,然后想繼續添加,如果browse_button不變(位置)沒事,而我遇到的是,繼續添加按鈕是在跟隨已添加圖片的后面,一開始覺得so easy,在事件FilesAdded重新設置選項browse_button,結果發現,之前添加的文件隊列丟了,也就是相當於plupload執行了refresh,重新搞,我想到將原來的browse_button移過來,文件沒丟失,在runtime為html5時,效果不錯。把代碼提交上去,然后測試mm給我提了一個bug,說在ie6,7,8,9繼續添加無效,倒騰了一個虛擬機裝上ie6,還真不管用,去網上找解決方案,然並卵,並沒有找到。只能自己琢磨了,在頁面上亂點一通,結果發現點擊原來的browse_button的位置可以彈出文件選擇框,想把plupload生成的object標簽移過來,還是沒有用,利用dom查看,發現object相對於container絕對定位,問題的點找到了,可以監控文件隊列長度,然后修改object標簽的位置,搞定。
vm.uploadPhotoList.$watch('length',function(len){ if(vm.currentRuntime == 'flash'){ var hot_zone = $('.moxie-shim'); if(hot_zone.length>0){ hot_zone.css({width:140,height:180}); if(len<5){ hot_zone.css({left:168*len,top:70}); }else if(len < 9){ hot_zone.css({left:168*(len-5),top:276}); } } } });
4.預覽圖片
之前也調研過,預覽圖片可能會使用到canvas,或者使用datauri(支持ie7+),ie6怎么辦,plupload中的moxie有個embed有如下描述
shim object (Flash or SilverLight - very rare, used for legacy browsers that do not have canvas or proper dataURI support,有了這句話,依據網上搜到的代碼示例,寫下了如下代碼
var preloader = new mOxie.Image(); preloader.onload = function() { this.embed('pic_'+file.id, { width: 138, height: 147, crop:true }); }; preloader.onembedded = function(){ this.destroy(); }; preloader.onerror = function(){ this.destroy(); }; preloader.load(file.getSource());
由於我的電腦是ie11,調試界面可以調整ie版本,自己的代碼跑了一下,竟然連ie5都兼容,覺得好開心,把代碼提交上去,然后測試mm說你的這個在ie6上怎么沒有預覽圖片啊,我說不可能啊,我的ie5都支持,我自己在虛擬機跑了一下,卧槽,還真不行。查看ie5下的dom結構,用的是datauri,好吧,看來ie的模擬版本不太可靠啊。去網上找解決方案,資料很少,並沒有什么有用的(我用的是google),去plupload的官方網站http://www.plupload.com看了一下它的demo,看到ui版本自帶預覽圖選項,需要添加如下代碼

1 resize : { 2 width : 200, 3 height : 200, 4 quality : 90, 5 crop: true // crop to exact dimensions 6 }, 7 8 // Views to activate 9 views: { 10 list: true, 11 thumbs: true, // Show thumbs 12 active: 'thumbs' 13 },
我並不想引入jquery ui,因為太大了,然后去看它的源碼,有了些眉目

1 function preloadThumb(file, cb) { 2 var img = new o.Image(); 3 4 img.onload = function() { 5 var thumb = $('#' + file.id + ' .plupload_file_thumb', self.filelist).html(''); 6 this.embed(thumb[0], { 7 width: self.options.thumb_width, 8 height: self.options.thumb_height, 9 crop: true, 10 swf_url: o.resolveUrl(self.options.flash_swf_url), 11 xap_url: o.resolveUrl(self.options.silverlight_xap_url) 12 }); 13 }; 14 15 img.bind("embedded error", function() { 16 $('#' + file.id, self.filelist).removeClass('plupload_file_loading'); 17 this.destroy(); 18 setTimeout(cb, 1); // detach, otherwise ui might hang (in SilverLight for example) 19 }); 20 21 img.load(file.getSource()); 22 }
我修改了我的預覽代碼,如下

1 var preloader = new mOxie.Image(); 2 preloader.onload = function() { 3 this.embed('pic_'+file.id, { 4 width: 138, 5 height: 147, 6 crop:true, 7 swf_url: o.resolveUrl(up.getOption('flash_swf_url')) 8 9 }); 10 }; 11 preloader.onembedded = function(){ 12 this.destroy(); 13 }; 14 preloader.onerror = function(){ 15 this.destroy(); 16 }; 17 preloader.load(file.getSource());
搞定,然而這種方式不支持gif的預覽,有時間再拿出來討論下
5.qiniu.js中的一些坑
上傳的文件公司都是存儲在第三方七牛雲上,七牛提供了很多sdk,開始准備用后端sdk做一下中轉,但效率不太好,然后就換成用qiniu.js(js sdk),我們需要兼容到ie6,然而qiniu.js兼容到ie8+(沒有考慮中國國情啊),之前也用過qiniu.js,只修改了源碼中的trim,后來七牛自己修改了,在上傳圖片,附件的時候並沒有發現什么異常。這次項目中需要上傳視頻,我在使用的過程中發現,ie6,7上傳視頻過程中fileuploaded事件無法觸發,可能跟后端給我的token有關,但圖片是ok的。去看qiniu.js關於fileuploaded事件封裝的源碼,

1 var info_extended = {}; 2 plupload.extend(info_extended, that.parseJSON(info), res_downtoken); 3 if (_FileUploaded_Handler) { 4 _FileUploaded_Handler(up, file, JSON.stringify(info_extended)); 5 }
我們知道,在ie6,7並沒有JSON對象,而這里在前文中也並沒有定義,找到原因了,引入了json2.js,視頻上傳正常了。最近一直在做附件上傳的項目,當頁面上有多種附件待上傳時,如果包含視頻、音頻則需要做持久化處理,后台給的token將會不一樣,此時如果直接用Qiniu.uploader()函數會導致所有的上傳都以最后拿到的token為准。繼續去看qiniu.js源碼,Qiniu這個變量是QiniuJsSDK的一個實例,我們只需要自己創建實例即可,也就是每次調用時new QiniuJsSDK().
結語
第一次寫,若有不對之處,望指正。