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)文章
Java使用excel工具類導(dǎo)出對(duì)象功能示例
這篇文章主要介紹了Java使用excel工具類導(dǎo)出對(duì)象功能,結(jié)合實(shí)例形式分析了java創(chuàng)建及導(dǎo)出Excel數(shù)據(jù)的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下2017-10-10
Java 如何實(shí)現(xiàn)一個(gè)http服務(wù)器
這篇文章主要介紹了Java 如何實(shí)現(xiàn)一個(gè)http服務(wù)器,幫助大家更好的理解和學(xué)習(xí)Java,感興趣的朋友可以了解下2020-11-11
spring在service層的方法報(bào)錯(cuò)事務(wù)不會(huì)回滾的解決
這篇文章主要介紹了spring在service層的方法報(bào)錯(cuò)事務(wù)不會(huì)回滾的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
Springboot項(xiàng)目出現(xiàn)java.lang.ArrayStoreException的異常分析
這篇文章介紹了Springboot項(xiàng)目出現(xiàn)java.lang.ArrayStoreException的異常分析,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-12-12
JavaWeb開(kāi)發(fā)基于ssm的校園服務(wù)系統(tǒng)(實(shí)例詳解)
這篇文章主要介紹了JavaWeb開(kāi)發(fā)基于ssm的校園服務(wù)系統(tǒng),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02
java 中Collection存儲(chǔ)器詳解及簡(jiǎn)單實(shí)例
這篇文章主要介紹了java 中Collection存儲(chǔ)器詳解及簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-04-04
MyBatis的配置對(duì)象Configuration作用及說(shuō)明
MyBatis的Configuration對(duì)象是MyBatis的核心配置對(duì)象,它包含了MyBatis運(yùn)行時(shí)所需的幾乎所有配置信息,這個(gè)對(duì)象負(fù)責(zé)管理MappedStatement、創(chuàng)建核心組件、提供配置信息的訪問(wèn)接口以及作為插件機(jī)制的入口2025-03-03

