Java中使用WebUploader插件上傳大文件單文件和多文件的方法小結(jié)
一.使用webuploader插件的原因說(shuō)明
被現(xiàn)在做的項(xiàng)目坑了。
先說(shuō)一下我的項(xiàng)目架構(gòu)spring+struts2+mybatis+MySQL
然后呢。之前說(shuō)好的按照2G上傳就可以了,于是乎,用了ajaxFileUpload插件,因?yàn)橹坝脠D片上傳也是用這個(gè),所以上傳附件的時(shí)候就直接拿來(lái)用了
各種碼代碼,測(cè)試也測(cè)過(guò)了,2G文件上傳沒(méi)問(wèn)題,坑來(lái)了,項(xiàng)目上線后,客戶又要求上傳4G文件,甚至還有20G以上的。。納尼,你不早說(shuō)哦。。。
在IE11下用ajaxFileUpload.js插件上傳超過(guò)4G的文件,IE直接拋出異常了。彈出 算術(shù)結(jié)果超過(guò)32位 的消息.
如下圖:
附加說(shuō)明一下,我的系統(tǒng)是64位,8G內(nèi)存,google瀏覽器和IE11瀏覽器都是32位的。google下用AjaxFileUpload上傳8G都問(wèn)題。都不會(huì)報(bào)錯(cuò)。
IE11下超過(guò)4G直接報(bào)上圖這個(gè)錯(cuò)了。沒(méi)辦法。換插件。
二.插件選擇
1.stream上傳插件。stream是解決不同瀏覽器上傳文件插件,是Uploadify的flash版和html5的結(jié)合。插件地址http://www.twinkling.cn/
功能確實(shí)很強(qiáng)大,不過(guò)CSS樣式固定死了,和我現(xiàn)在項(xiàng)目的進(jìn)度條樣式很不一樣。還是放棄了這個(gè)插件
2.Webuploader 插件。WebUploader是由Baidu WebFE(FEX)團(tuán)隊(duì)開(kāi)發(fā)的一個(gè)簡(jiǎn)單的以HTML5為主,F(xiàn)LASH為輔的現(xiàn)代文件上傳組件。在現(xiàn)代的瀏覽器里面能充分發(fā)揮HTML5的優(yōu)勢(shì),同時(shí)又不摒棄主流IE瀏覽器,沿用原來(lái)的FLASH運(yùn)行時(shí),兼容IE6+,iOS 6+, Android 4+。兩套運(yùn)行時(shí),同樣的調(diào)用方式,可供用戶任意選用。
采用大文件分片并發(fā)上傳,極大的提高了文件上傳效率。插件地址 http://fex.baidu.com/webuploader/
這個(gè)插件可以自定義CSS樣式啊。功能也很強(qiáng)大,于是乎果斷采用這個(gè)插件。
三.WebUploader 單文件上傳
我用的是Webuploader0.1.5版本的,Webuploader主要是把大文件在客戶端進(jìn)行分片,比如按照每5M進(jìn)行分片發(fā)送請(qǐng)求,后臺(tái)接收到文件進(jìn)行合并文件。兩種方式合并文件,第一種等所有分片都傳到后臺(tái),然后在合并,這種要保障分片順序正確,第二種是邊分片邊合并。項(xiàng)目里我使用的是第二種。使用Web Uploader文件上傳需要引入三種資源:JS, CSS, SWF。
1.引入JS文件
<script type="text/javascript" src="../main/js/webuploader.js"></script> <script type="text/javascript" src="../main/js/webuploader.min.js"></script>
2.引入CSS樣式
<link href="../main/css/webuploader.css" rel="stylesheet" type="text/css" />
3.引入SWF,SWF不直接引用,在webUploader初始化的時(shí)候指定SWF的路徑就可以了。
4.upload3.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-Language" content="ja" /> <meta http-equiv="Content-Script-Type" content="text/javascript" /> <meta http-equiv="Content-Style-Type" content="text/css" /> <title>DEMO</title> <link href="../main/css/stream-v1.css" rel="stylesheet" type="text/css" /> <link href="../main/css/webuploader.css" rel="stylesheet" type="text/css" /> <script type="text/javascript" src="../main/js/jquery-1.11.1.min.js"></script> <script type="text/javascript" src="../main/js/jquery-2.1.4.min.js"></script> <script type="text/javascript" src="../main/js/jquery-ui.min.js"></script> <script type="text/javascript" src="../main/js/bootstrap-datepicker.min.js"></script> <script type="text/javascript" src="../main/js/locales/bootstrap-datepicker.ja.min.js"></script> <script type="text/javascript" src="../main/js/webuploader.js"></script> <script type="text/javascript" src="../main/js/webuploader.min.js"></script> <script type="text/javascript" src="../js/contents/upload3.js"></script> </head> <body> <div id="uploader" class="wu-example"> <!--用來(lái)存放文件信息--> <div id="thelist" class="uploader-list"></div> <div class="btns"> <div id="attach"></div> <input type="button" value="上傳" id="upload"/> </div> </div> <div id="uploader1" class="wu-example"> <!--用來(lái)存放文件信息--> <div id="thelist1" class="uploader-list"></div> <div class="btns"> <div id="multi"></div> <input type="button" value="上傳" id="multiUpload"/> </div> </div> </body> </html>
畫(huà)面比較簡(jiǎn)單,長(zhǎng)這個(gè)樣子
5.upload3.js
包含單文件上傳,多文件上傳,和webuploader多實(shí)例
/*********************************WebUpload 單文件上傳 begin*****************************************/ $(function(){ var $list = $("#thelist"); var uploader ;// 實(shí)例化 uploader = WebUploader.create({ auto:false, //是否自動(dòng)上傳 pick: { id: '#attach', name:"file", //這個(gè)地方 name 沒(méi)什么用,雖然打開(kāi)調(diào)試器,input的名字確實(shí)改過(guò)來(lái)了。但是提交到后臺(tái)取不到文件。如果想自定義file的name屬性,還是要和fileVal 配合使用。 label: '點(diǎn)擊選擇圖片', multiple:false //默認(rèn)為true,就是可以多選 }, swf: '../../main/js/Uploader.swf', //fileVal:'multiFile', //自定義file的name屬性,我用的版本是0.1.5 ,打開(kāi)客戶端調(diào)試器發(fā)現(xiàn)生成的input 的name 沒(méi)改過(guò)來(lái)。 //名字還是默認(rèn)的file,但不是沒(méi)用哦。雖然客戶端名字沒(méi)改變,但是提交到到后臺(tái),是要用multiFile 這個(gè)對(duì)象來(lái)取文件的,用file 是取不到文件的 // 建議作者有時(shí)間把這個(gè)地方改改啊,搞死人了。。 server: "ContentsDetail!ajaxAttachUpload.action", duplicate:true,//是否可重復(fù)選擇同一文件 resize: false, formData: { "status":"file", "contentsDto.contentsId":"0000004730", "uploadNum":"0000004730", "existFlg":'false' }, compress: null,//圖片不壓縮 chunked: true, //分片處理 chunkSize: 5 * 1024 * 1024, //每片5M chunkRetry:false,//如果失敗,則不重試 threads:1,//上傳并發(fā)數(shù)。允許同時(shí)最大上傳進(jìn)程數(shù)。 // runtimeOrder: 'flash', // 禁掉全局的拖拽功能。這樣不會(huì)出現(xiàn)圖片拖進(jìn)頁(yè)面的時(shí)候,把圖片打開(kāi)。 disableGlobalDnd: true }); // 當(dāng)有文件添加進(jìn)來(lái)的時(shí)候 uploader.on( "fileQueued", function( file ) { console.log("fileQueued:"); $list.append( "<div id='"+ file.id + "' class='item'>" + "<h4 class='info'>" + file.name + "</h4>" + "<p class='state'>等待上傳...</p>" + "</div>" ); }); //當(dāng)所有文件上傳結(jié)束時(shí)觸發(fā) uploader.on("uploadFinished",function(){ console.log("uploadFinished:"); }) //當(dāng)某個(gè)文件上傳到服務(wù)端響應(yīng)后,會(huì)派送此事件來(lái)詢問(wèn)服務(wù)端響應(yīng)是否有效。 uploader.on("uploadAccept",function(object,ret){ //服務(wù)器響應(yīng)了 //ret._raw 類似于 data var data =JSON.parse(ret._raw); if(data.resultCode != "1" && data.resultCode != "3"){ if(data.resultCode == "9"){ uploader.reset(); alert("error"); return false; } }else{ //E05017 uploader.reset(); alert("error"); return false; } }) //當(dāng)文件上傳成功時(shí)觸發(fā)。 uploader.on( "uploadSuccess", function( file ) { $( "#"+file.id ).find("p.state").text("已上傳"); }); uploader.on( "uploadError", function( file ) { $( "#"+file.id ).find("p.state").text("上傳出錯(cuò)"); uploader.cancelFile(file); uploader.removeFile(file,true); uploader.reset(); }); $("#upload").on("click", function() { uploader.upload(); }) }); /*********************************WebUpload 單文件上傳 end*******************************************/ /*********************************WebUpload 多文件上傳 begin*****************************************/ $(function(){ var $list = $("#thelist1"); var fileSize = 0; //總文件大小 var fileName = []; //文件名列表 var fileSizeOneByOne =[];//每個(gè)文件大小 var uploader ;// 實(shí)例化 uploader = WebUploader.create({ auto:false, //是否自動(dòng)上傳 pick: { id: '#multi', label: '點(diǎn)擊選擇文件', name:"multiFile" }, swf: '../../main/js/Uploader.swf', server: "ContentsDetail!multiUpload.action", duplicate:true, //同一文件是否可重復(fù)選擇 resize: false, formData: { "status":"multi", "contentsDto.contentsId":"0000004730", "uploadNum":"0000004730", "existFlg":'false' }, compress: null,//圖片不壓縮 chunked: true, //分片 chunkSize: 5 * 1024 * 1024, //每片5M chunkRetry:false,//如果失敗,則不重試 threads:1,//上傳并發(fā)數(shù)。允許同時(shí)最大上傳進(jìn)程數(shù)。 //fileNumLimit:50,//驗(yàn)證文件總數(shù)量, 超出則不允許加入隊(duì)列 // runtimeOrder: 'flash', // 禁掉全局的拖拽功能。這樣不會(huì)出現(xiàn)圖片拖進(jìn)頁(yè)面的時(shí)候,把圖片打開(kāi)。 disableGlobalDnd: true }); // 當(dāng)有文件添加進(jìn)來(lái)的時(shí)候 uploader.on( "fileQueued", function( file ) { console.log("fileQueued:"); $list.append( "<div id='"+ file.id + "' class='item'>" + "<h4 class='info'>" + file.name + "</h4>" + "<p class='state'>等待上傳...</p>" + "</div>" ); }); // 當(dāng)開(kāi)始上傳流程時(shí)觸發(fā) uploader.on( "startUpload", function() { console.log("startUpload"); //添加額外的表單參數(shù) $.extend( true, uploader.options.formData, {"fileSize":fileSize,"multiFileName":fileName.join(","),"fileSizeOneByOne":fileSizeOneByOne.join(",")}); }); //當(dāng)某個(gè)文件上傳到服務(wù)端響應(yīng)后,會(huì)派送此事件來(lái)詢問(wèn)服務(wù)端響應(yīng)是否有效。 uploader.on("uploadAccept",function(object,ret){ //服務(wù)器響應(yīng)了 //ret._raw 類似于 data console.log("uploadAccept"); console.log(ret); var data =JSON.parse(ret._raw); if(data.resultCode!="1" && data.resultCode !="3"){ if(data.resultCode == "9"){ alert("error"); uploader.reset(); return; } }else{ uploader.reset(); alert("error"); } }) uploader.on( "uploadSuccess", function( file ) { $( "#"+file.id ).find("p.state").text("已上傳"); }); uploader.on( "uploadError", function( file,reason ) { $( "#"+file.id ).find("p.state").text("上傳出錯(cuò)"); console.log("uploadError"); console.log(file); console.log(reason); //多個(gè)文件 var fileArray = uploader.getFiles(); for(var i = 0 ;i<fileArray.length;i++){ uploader.cancelFile(fileArray[i]); uploader.removeFile(fileArray[i],true); } uploader.reset(); fileSize = 0; fileName = []; fileSizeOneByOne=[]; }); //當(dāng)validate不通過(guò)時(shí),會(huì)以派送錯(cuò)誤事件的形式通知調(diào)用者 uploader.on("error",function(){ console.log("error"); uploader.reset(); fileSize = 0; fileName = []; fileSizeOneByOne=[]; alert("error"); }) //如果是在模態(tài)框里的上傳按鈕,點(diǎn)擊file的時(shí)候不會(huì)觸發(fā)控件 //修復(fù)model內(nèi)部點(diǎn)擊不會(huì)觸發(fā)選擇文件的BUG /* $("#multi .webuploader-pick").click(function () { uploader.reset(); fileSize = 0; fileName = []; fileSizeOneByOne=[]; $("#multi :file").click();//關(guān)鍵代碼 });*/ //選擇文件之后執(zhí)行上傳 $(document).on("change","input[name='multiFile']", function() { var fileArray1 = uploader.getFiles(); for(var i = 0 ;i<fileArray1.length;i++){ //后臺(tái)用 fileSize +=fileArray1[i].size; fileSizeOneByOne.push(fileArray1[i].size); fileName.push(fileArray1[i].name); } console.log(fileSize); console.log(fileSizeOneByOne); console.log(fileName); }) /** * 多文件上傳 */ $("input[name='multiUpload']").on("click",function(){ uploader.upload(); }) }); /*********************************WebUpload 多文件上傳 end*****************************************/ /************************************webuploader的自帶參數(shù)提交到后臺(tái)的參數(shù)列表************************* * { //web uploader 的自帶參數(shù) lastModifiedDate=[Wed Apr 27 2016 16:45:01 GMT+0800 (中國(guó)標(biāo)準(zhǔn)時(shí)間)], chunks=[3], chunk=[0], type=[audio/wav], uid=[yangl], id=[WU_FILE_0], size=[268620636], name=[3.wav], //formData的參數(shù) contentsDto.contentsId=[0000004730], existFlg=[false], status=[file], uploadNum=[0000004730] } *********************************************************************************************/
6.ContentsDetail.action
//單文件上傳后臺(tái)代碼 public void ajaxAttachUpload() { String path = "d:\\test\\"+fileFileName; try { File file = this.getFile(); FileUtil.randomAccessFile(path, file); //如果文件小與5M的話,分片參數(shù)chunk的值是null if(StringUtils.isEmpty(chunk)){ outJson("0", "success", ""); }else{ //chunk 分片索引,下標(biāo)從0開(kāi)始 //chunks 總分片數(shù) if (Integer.valueOf(chunk) == (Integer.valueOf(chunks) - 1)) { outJson("0", "上傳成功", ""); } else { outJson("2", "上傳中" + fileFileName + " chunk:" + chunk, ""); } } } catch (Exception e) { outJson("3", "上傳失敗", ""); } }
FileUtil.java
/** * 指定位置開(kāi)始寫(xiě)入文件 * @param tempFile 輸入文件 * @param outPath 輸出文件的路徑(路徑+文件名) * @throws IOException */ public static void randomAccessFile( String outPath,File tempFile) throws IOException{ RandomAccessFile raFile = null; BufferedInputStream inputStream=null; try{ File dirFile = new File(outPath); //以讀寫(xiě)的方式打開(kāi)目標(biāo)文件 raFile = new RandomAccessFile(dirFile, "rw"); raFile.seek(raFile.length()); inputStream = new BufferedInputStream(new FileInputStream(tempFile)); byte[] buf = new byte[1024]; int length = 0; while ((length = inputStream.read(buf)) != -1) { raFile.write(buf, 0, length); } }catch(Exception e){ throw new IOException(e.getMessage()); }finally{ try { if (inputStream != null) { inputStream.close(); } if (raFile != null) { raFile.close(); } }catch(Exception e){ throw new IOException(e.getMessage()); } } }
7.效果圖
以上所述是小編給大家介紹的Java中使用WebUploader插件上傳大文件單文件和多文件的方法小結(jié)的相關(guān)知識(shí),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
SpringMvc/SpringBoot HTTP通信加解密的實(shí)現(xiàn)
這篇文章主要介紹了SpringMvc/SpringBoot HTTP通信加解密的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08解決SpringBoot2多線程無(wú)法注入的問(wèn)題
這篇文章主要介紹了解決SpringBoot2多線程無(wú)法注入的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08SpringBoot2 集成log4j2日志框架的實(shí)現(xiàn)
這篇文章主要介紹了SpringBoot2 集成log4j2日志框架的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10MyBatis開(kāi)發(fā)Dao層的兩種方式實(shí)現(xiàn)(原始Dao層開(kāi)發(fā))
這篇文章主要介紹了MyBatis開(kāi)發(fā)Dao層的兩種方式實(shí)現(xiàn)(原始Dao層開(kāi)發(fā)),并對(duì)數(shù)據(jù)庫(kù)進(jìn)行增刪查改,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12Java 創(chuàng)建線程的兩個(gè)方法詳解及實(shí)例
這篇文章主要介紹了Java 創(chuàng)建線程的兩個(gè)方法詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-03-03Graceful Response 構(gòu)建 Spring Boot 響應(yīng)
Graceful Response是一個(gè)Spring Boot技術(shù)棧下的優(yōu)雅響應(yīng)處理器,提供一站式統(tǒng)一返回值封裝、全局異常處理、自定義異常錯(cuò)誤碼等功能,本文介紹Graceful Response 構(gòu)建 Spring Boot 下優(yōu)雅的響應(yīng)處理,感興趣的朋友一起看看吧2024-01-01