需求:項目要支持大文件上傳功能,經(jīng)過討論没龙,初步將文件上傳大小控制在500M內(nèi)链韭,因此自己需要在項目中進行文件上傳部分的調(diào)整和配置,自己將大小都以501M來進行限制窍株。
第一步:
前端修改
由于項目使用的是BJUI前端框架民轴,并沒有使用框架本身的文件上傳控件,而使用的基于jQuery的Uploadify文件上傳組件球订,在項目使用的jslib項目中找到了BJUI框架集成jQuery Uploadify的部分,這部分代碼封裝在bjui-all.js文件中冒滩,
在bjui-all.js文件中的全局變量定義中有以下部分代碼微驶,這就是定義的有關(guān)于上傳的Uploadify控件的重要變量:
//文件上傳對象
function?FileUploader(fileLoc, mgr)
{
?var?_this =?this;
?this.id = fileLoc.id;
?this.ui = { msg:?null, process:?null, percent:?null, btn: { del:?null, cancel:?null,post:null,stop:null?}, div:?null};
?this.isFolder =?false;?//不是文件夾
?this.app = mgr.app;
?this.Manager = mgr;?//上傳管理器指針
?this.event = mgr.event;
?this.Config = mgr.Config;
?this.fields = jQuery.extend({}, mgr.Config.Fields, fileLoc.fields);//每一個對象自帶一個fields幅本
?this.State =?this.Config.state.None;
?this.uid =?this.fields.uid;
?this.fileSvr = {
?pid:?""
?, id:?""
?, pidRoot:?""
?, f_fdTask:?false
?, f_fdChild:?false
?, uid: 0
?, nameLoc:?""
?, nameSvr:?""
?, pathLoc:?""
?, pathSvr:?""
?, pathRel:?""
?, md5:?""
?, lenLoc:?"0"
?, sizeLoc:?""
?, FilePos:?"0"
?, lenSvr:?"0"
?, perSvr:?"0%"
?, complete:?false
?, deleted:?false
?};//json obj士八,服務(wù)器文件信息
?this.fileSvr = jQuery.extend(this.fileSvr, fileLoc);
?//準(zhǔn)備
?this.Ready =?function?()
?{
?this.ui.msg.text("正在上傳隊列中等待...");
?this.State =?this.Config.state.Ready;
?this.ui.btn.post.click(function?() {
?_this.ui.btn.post.hide();
?_this.ui.btn.del.hide();
?_this.ui.btn.cancel.hide();
?_this.ui.btn.stop.show();
?if?(!_this.Manager.IsPostQueueFull()) {
?_this.post();
?}
?else?{
?_this.ui.msg.text("正在上傳隊列中等待...");
?_this.State = _this.Config.state.Ready;
?$.each(_this.ui.btn,?function?(i, n) { n.hide(); });
?_this.ui.btn.del.show();
?//添加到隊列
?_this.Manager.AppendQueue(_this.fileSvr.id);
????????}
?});
?this.ui.btn.stop.click(function?() {
?_this.stop();
?});
?this.ui.btn.del.click(function?() {
?_this.stop();
?_this.remove();
?});
?this.ui.btn.cancel.click(function?() {
?_this.stop();
?_this.remove();
?//_this.PostFirst();//
?});
?};
?this.svr_error =?function?()
?{
?alert("服務(wù)器返回信息為空醋虏,請檢查服務(wù)器配置");
?this.ui.msg.text("向服務(wù)器發(fā)送MD5信息錯誤");
?//this.ui.btn.cancel.text("續(xù)傳");
?this.ui.btn.stop.hide();
?this.ui.btn.cancel.show();
?};
?this.svr_error_same_name =?function?() {???????
?this.ui.msg.text("服務(wù)器存在同名文件");
?this.ui.btn.stop.hide();
?this.ui.btn.cancel.show();
?};
?this.svr_create =?function?(sv)
?{
?if?(sv.value ==?null)
?{
?this.Manager.RemoveQueuePost(this.fileSvr.id);
?this.svr_error();?return;
?}
?if?(!sv.ret) {
?this.Manager.RemoveQueuePost(this.fileSvr.id);
?this.svr_error_same_name();?return;
?}
?var?str = decodeURIComponent(sv.value);//
?this.fileSvr = JSON.parse(str);//
?//服務(wù)器已存在相同文件叫挟,且已上傳完成
?if?(this.fileSvr.complete)
?{
?this.post_complete_quick();
?}?//服務(wù)器文件沒有上傳完成
?else
?{
?this.ui.process.css("width",?this.fileSvr.perSvr);
?this.ui.percent.text(this.fileSvr.perSvr);
?this.post_file();
?}
?};
?this.svr_update =?function?() {
?if?(this.fileSvr.lenSvr == 0)?return;
?var?param = { uid:?this.fields["uid"], offset:?this.fileSvr.lenSvr, lenSvr:?this.fileSvr.lenSvr, perSvr:?this.fileSvr.perSvr, id:?this.id, time:?new?Date().getTime() };
?$.ajax({
?type:?"GET"
?, dataType:?'jsonp'
?, jsonp:?"callback"?//自定義的jsonp回調(diào)函數(shù)名稱,默認為jQuery自動生成的隨機函數(shù)名
?, url:?this.Config["UrlProcess"]
?, data: param
?, success:?function?(msg) {}
?, error:?function?(req, txt, err) { alert("更新文件進度錯誤!"?+ req.responseText); }
?, complete:?function?(req, sta) { req =?null; }
?});
?};
?this.svr_remove =?function?()
?{
?var?param = { uid:?this.fields["uid"], id:?this.fileSvr.id, time:?new?Date().getTime() };
?$.ajax({
?type:?"GET"
?, dataType:?'jsonp'
?, jsonp:?"callback"?//自定義的jsonp回調(diào)函數(shù)名稱,默認為jQuery自動生成的隨機函數(shù)名
?, url:?this.Config["UrlDel"]
?, data: param
?, success:?function?(msg) { }
?, error:?function?(req, txt, err) { alert("刪除文件失敗凌节!"?+ req.responseText); }
?, complete:?function?(req, sta) { req =?null; }
?});
?};
?this.post_process =?function?(json)
?{
?this.fileSvr.lenSvr = json.lenSvr;//保存上傳進度
?this.fileSvr.perSvr = json.percent;
?this.ui.percent.text("("+json.percent+")");
?this.ui.process.css("width", json.percent);
?var?str = json.lenPost +?" "?+ json.speed +?" "?+ json.time;
?this.ui.msg.text(str);
?};
?this.post_complete =?function?(json)
?{
?this.fileSvr.perSvr =?"100%";
?this.fileSvr.complete =?true;
?$.each(this.ui.btn,?function?(i, n)
?{
?n.hide();
?});
?this.ui.process.css("width",?"100%");
?this.ui.percent.text("(100%)");
?this.ui.msg.text("上傳完成");
?this.Manager.arrFilesComplete.push(this);
?this.State =?this.Config.state.Complete;
??????//從上傳列表中刪除
?this.Manager.RemoveQueuePost(this.fileSvr.id);
?//從未上傳列表中刪除
?this.Manager.RemoveQueueWait(this.fileSvr.id);
?var?param = { md5:?this.fileSvr.md5, uid:?this.uid, id:?this.fileSvr.id, time:?new?Date().getTime() };
?$.ajax({
?type:?"GET"
?, dataType:?'jsonp'
?, jsonp:?"callback"?//自定義的jsonp回調(diào)函數(shù)名稱,默認為jQuery自動生成的隨機函數(shù)名
?, url: _this.Config["UrlComplete"]
?, data: param
?, success:?function?(msg)
?{
??_this.event.fileComplete(_this);//觸發(fā)事件
??_this.post_next();
?}
?, error:?function?(req, txt, err) { alert("文件-向服務(wù)器發(fā)送Complete信息錯誤!"?+ req.responseText); }
?, complete:?function?(req, sta) { req =?null; }
?});
?};
?this.post_complete_quick =?function?()
?{
???this.fileSvr.perSvr =?"100%";
?this.fileSvr.complete =?true;
?this.ui.btn.stop.hide();
?this.ui.process.css("width",?"100%");
?this.ui.percent.text("(100%)");
?this.ui.msg.text("服務(wù)器存在相同文件具练,快速上傳成功。");
?this.Manager.arrFilesComplete.push(this);
?this.State =?this.Config.state.Complete;
?//從上傳列表中刪除
?this.Manager.RemoveQueuePost(this.fileSvr.id);
?//從未上傳列表中刪除
?this.Manager.RemoveQueueWait(this.fileSvr.id);
?//添加到文件列表
?this.post_next();
?this.event.fileComplete(this);//觸發(fā)事件
?};
?this.post_stoped =?function?(json)
?{
?this.ui.btn.post.show();
?this.ui.btn.del.show();
?this.ui.btn.cancel.hide();
?this.ui.btn.stop.hide();
?this.ui.msg.text("傳輸已停止....");
?if?(this.Config.state.Ready ==?this.State)
?{
?this.Manager.RemoveQueue(this.fileSvr.id);
?this.post_next();
?return;
?}
?this.State =?this.Config.state.Stop;
?//從上傳列表中刪除
?this.Manager.RemoveQueuePost(this.fileSvr.id);
?this.Manager.AppendQueueWait(this.fileSvr.id);//添加到未上傳列表
?//傳輸下一個
?this.post_next();
?};
?this.post_error =?function?(json)
?{
?this.svr_update();
?this.ui.msg.text(this.Config.errCode[json.value]);
?this.ui.btn.stop.hide();
?this.ui.btn.post.show();
?this.ui.btn.del.show();
?this.State =?this.Config.state.Error;
?//從上傳列表中刪除
?this.Manager.RemoveQueuePost(this.fileSvr.id);
?//添加到未上傳列表
?this.Manager.AppendQueueWait(this.fileSvr.id);
?this.post_next();
?};
?this.md5_process =?function?(json)
?{
?var?msg =?"正在掃描本地文件铜邮,已完成:"?+ json.percent;
?this.ui.msg.text(msg);
?};
?this.md5_complete =?function?(json)
?{
?this.fileSvr.md5 = json.md5;
?this.ui.msg.text("MD5計算完畢咖摹,開始連接服務(wù)器...");
?this.event.md5Complete(this, json.md5);//biz event
?var?loc_path = encodeURIComponent(this.fileSvr.pathLoc);
?var?loc_len =?this.fileSvr.lenLoc;
?var?loc_size =?this.fileSvr.sizeLoc;
?var?param = jQuery.extend({},?this.fields,?this.Config.bizData, { md5: json.md5, id:?this.fileSvr.id, lenLoc: loc_len, sizeLoc: loc_size, pathLoc: loc_path, time:?new?Date().getTime() });
?$.ajax({
?type:?"GET"
?, dataType:?'jsonp'
?, jsonp:?"callback"?//自定義的jsonp回調(diào)函數(shù)名稱,默認為jQuery自動生成的隨機函數(shù)名
?, url:?this.Config["UrlCreate"]
?, data: param
?, success:?function?(sv)
?{
?_this.svr_create(sv);
?}
?, error:?function?(req, txt, err)
?{
?_this.Manager.RemoveQueuePost(_this.fileSvr.id);
?alert("向服務(wù)器發(fā)送MD5信息錯誤!"?+ req.responseText);
?_this.ui.msg.text("向服務(wù)器發(fā)送MD5信息錯誤");
?_this.ui.btn.cancel.show();
?_this.ui.btn.stop.hide();
?}
?, complete:?function?(req, sta) { req =?null; }
?});
?};
?this.md5_error =?function?(json)
?{
?this.ui.msg.text(this.Config.errCode[json.value]);
?//文件大小超過限制,文件大小為0
?if?("4"?== json.value
?||?"5"?== json.value)
?{
?this.ui.btn.stop.hide();
?this.ui.btn.cancel.show();
?}
?else
?{???????????
?this.ui.btn.post.show();
?this.ui.btn.stop.hide();
?}
?this.State =?this.Config.state.Error;
?//從上傳列表中刪除
?this.Manager.RemoveQueuePost(this.fileSvr.id);
?//添加到未上傳列表
?this.Manager.AppendQueueWait(this.fileSvr.id);
?this.post_next();
?};
?this.post_next =?function?()
?{
?var?obj =?this;
?setTimeout(function?() { obj.Manager.PostNext(); }, 300);
?};
?this.post =?function?()
?{
?this.Manager.AppendQueuePost(this.fileSvr.id);
?this.Manager.RemoveQueueWait(this.fileSvr.id);
?if?(this.fileSvr.md5.length > 0 ||?this.fileSvr.lenSvr > 0)
?{
?this.post_file();
?}
?else
?{
?this.check_file();
?}
?};
?this.post_file =?function?()
?{
?$.each(this.ui.btn,?function?(i, n) { n.hide();});
?this.ui.btn.stop.show();
?this.State =?this.Config.state.Posting;//
?this.app.postFile({ id:?this.fileSvr.id, pathLoc:?this.fileSvr.pathLoc, pathSvr:this.fileSvr.pathSvr,lenSvr:?this.fileSvr.lenSvr, fields:?this.fields });
?};
?this.check_file =?function?()
?{
?//this.ui.btn.cancel.text("停止").show();
?this.ui.btn.stop.show();
?this.ui.btn.cancel.hide();
?this.State =?this.Config.state.MD5Working;
?this.app.checkFile({ id:?this.fileSvr.id, pathLoc:?this.fileSvr.pathLoc });
?};
?this.stop =?function?()
?{
?$.each(this.ui.btn,?function?(i, n) { n.hide();});
?this.svr_update();
?this.app.stopFile({ id:?this.fileSvr.id });???????
?};
?//手動停止文虏,一般在StopAll中調(diào)用
?this.stop_manual =?function?()
?{
?if?(this.Config.state.Posting ==?this.State)
?{
?this.svr_update();
?this.ui.btn.post.show();
?this.ui.btn.stop.hide();
?this.ui.btn.cancel.hide();
?this.ui.msg.text("傳輸已停止....");
?this.app.stopFile({ id:?this.fileSvr.id ,tip:false});
?this.State =?this.Config.state.Stop;
?}
?};
?//刪除年鸳,一般在用戶點擊"刪除"按鈕時調(diào)用
?this.remove =?function?()
?{
?this.Manager.del_file(this.fileSvr.id);
?this.app.delFile(this.fileSvr);
?this.ui.div.remove();
?if?(this.State !=?this.Config.state.Complete)?this.svr_remove();
?};
}
upload:{uploadLimit:5,fileSizeLimit:31744,removeTimeout:0.8}
以上三個變量代表的含義是:
uploadLimit:表示上傳文件個數(shù)的限制搔确,5表示文件上傳個數(shù)限制是5個
fileSizeLimit:表示上傳文件大小的限制,31744單位是KB瘦真,也就是表示31M
removeTimeout:表示移除文件的時間限制
繼續(xù)查找使用到這些變量的地方,看到了文件大小超出限制等
了解了BJUI前端框架對于上傳大文件的限制您机,可以這樣使用仲闽,增大文件上傳大小和數(shù)量,可以按照如下進行修改验庙,我們在bjui-all.js文件看到uploadLimit屬性和fileSizeLimit屬性的限制搞莺,我們在jsp文件中可以這樣進行替換腮敌,這里使用的是覆蓋原則澈圈,重新定義uploadLimit屬性和fileSizeLimit屬性压怠,覆蓋bjui-all.js文件的默認值設(shè)置这弧。
bjui-all.js文件的uploadLimit屬性和fileSizeLimit屬性對應(yīng)到j(luò)sp文件中的屬性就應(yīng)該這樣寫冷溶,data-upload-limit屬性和data-file-size-limit屬性逞频,只需要在后面改寫為data-upload-limit=“800”和data-file-size-limit=“5131264”即可,一定要注意這里的單位是KB刨疼,以上數(shù)字表示501M缝龄。
關(guān)于Uploadify控件屬性可以參考這篇文章也可以直接看官網(wǎng)文檔:
http://blog.ncmem.com/wordpress/2019/08/07/java超大文件上傳與下載/
屬性名稱默認值說明
autotrue設(shè)置為true當(dāng)選擇文件后就直接上傳了俺亮,為false需要點擊上傳按鈕才上傳 。
buttonClass”按鈕樣式
buttonCursor‘hand’鼠標(biāo)指針懸停在按鈕上的樣子
buttonImagenull瀏覽按鈕的圖片的路徑 疟呐。
buttonText‘SELECT FILES’瀏覽按鈕的文本脚曾。
checkExistingfalse文件上傳重復(fù)性檢查程序,檢查即將上傳的文件在服務(wù)器端是否已存在萨醒,存在返回1斟珊,不存在返回0
debugfalse如果設(shè)置為true則表示啟用SWFUpload的調(diào)試模式
fileObjName‘Filedata’文件上傳對象的名稱,如果命名為’the_files’,PHP程序可以用$_FILES['the_files']來處理上傳的文件對象囤踩。
fileSizeLimit0上傳文件的大小限制 旨椒,如果為整數(shù)型則表示以KB為單位的大小,如果是字符串堵漱,則可以使用(B, KB, MB, or GB)為單位综慎,比如’2MB’;
如果設(shè)置為0則表示無限制
fileTypeDesc‘All Files’這個屬性值必須設(shè)置fileTypeExts屬性后才有效勤庐,用來設(shè)置選擇文件對話框中的提示文本示惊,如設(shè)置fileTypeDesc為“請選擇rar doc pdf文件”
fileTypeExts‘*.*’設(shè)置可以選擇的文件的類型,格式如:’*.doc;*.pdf;*.rar’?愉镰。
formData?JSON格式上傳每個文件的同時提交到服務(wù)器的額外數(shù)據(jù)米罚,可在’onUploadStart’事件中使用’settings’方法動態(tài)設(shè)置。
height30設(shè)置瀏覽按鈕的高度 丈探,默認值
itemTemplatefalse用于設(shè)置上傳隊列的HTML模版录择,可以使用以下標(biāo)簽:
??instanceID – ? Uploadify實例的ID
??fileID – 列隊中此文件的ID,或者理解為此任務(wù)的ID
??fileName – 文件的名稱
??fileSize – 當(dāng)前上傳文件的大小
??插入模版標(biāo)簽時使用格式如:${fileName}
methodPost提交方式Post或Get
multitrue設(shè)置為true時可以上傳多個文件。
overrideEvents?設(shè)置哪些事件可以被重寫碗降,JSON格式隘竭,如:’overrideEvents’ : ['onUploadProgress']
preventCachingtrue如果為true,則每次上傳文件時自動加上一串隨機字符串參數(shù)讼渊,防止URL緩存影響上傳結(jié)果
progressData‘percentage’設(shè)置上傳進度顯示方式动看,percentage顯示上傳百分比,speed顯示上傳速度
queueIDfalse設(shè)置上傳隊列容器DOM元素的ID爪幻,如果為false則自動生成一個隊列容器菱皆。
queueSizeLimit999隊列最多顯示的任務(wù)數(shù)量,如果選擇的文件數(shù)量超出此限制笔咽,將會出發(fā)onSelectError事件搔预。
??注意此項并非最大文件上傳數(shù)量,如果要限制最大上傳文件數(shù)量叶组,應(yīng)設(shè)置uploadLimit。
removeCompletedtrue是否自動將已完成任務(wù)從隊列中刪除历造,如果設(shè)置為false則會一直保留此任務(wù)顯示甩十。
removeTimeout3如果設(shè)置了任務(wù)完成后自動從隊列中移除,則可以規(guī)定從完成到被移除的時間間隔吭产。
requeueErrorsfalse如果設(shè)置為true侣监,則單個任務(wù)上傳失敗后將返回錯誤,并重新加入任務(wù)隊列上傳臣淤。
successTimeout30文件上傳成功后服務(wù)端應(yīng)返回成功標(biāo)志橄霉,此項設(shè)置返回結(jié)果的超時時間
swf‘uploadify.swf’uploadify.swf?文件的相對路徑。
uploaderuploadify.php后臺處理程序的相對路徑邑蒋。
uploadLimit999最大上傳文件數(shù)量姓蜂,如果達到或超出此限制將會觸發(fā)onUploadError事件按厘。
width120設(shè)置文件瀏覽按鈕的寬度。
第二步:
后端修改
由于項目后端使用的Spring Boot钱慢,本身也就是使用的Spring MVC文件上傳部分逮京,Spring MVC使用的是已經(jīng)對Servlet文件上傳封裝了的MultipartResolver接口及其相關(guān)實現(xiàn)類和一些相關(guān)的類,具體的可以看Spring MVC文件上傳源碼部分束莫,認為Spring源碼還是需要讀的懒棉,我們只要在Spring Boot啟動類中注入這個Bean,或者自行寫一個WebConfig配置類览绿,注入一些Web相關(guān)的Bean即可策严,這樣Spring Boot啟動就會加載配置類,也需要自己寫攔截器和全局AOP切面饿敲,去捕捉文件上傳大小超過限制的異常處理等
基于Spring MVC文件上傳組件MultipartResolver接口(核心)妻导,使用其中的CommonsMultipartResolver(實現(xiàn)了MultipartResolver接口)這個實現(xiàn)類,CommonsMultipartResolver中的maxUploadSize屬性是它繼承的抽象父類CommonsFileUploadSupport诀蓉,這個抽象類其中的一個屬性是FileUpload類栗竖,而這個類又繼承自FileUploadBase這個抽象類,其中它的private long sizeMax = -1;就是maxUploadSize屬性的最終設(shè)置地方渠啤。-1表示文件上傳大小沒有限制狐肢,但是我們一般都會設(shè)置一個限制值,這里設(shè)置的是210763776沥曹,這個值的單位是字節(jié)份名,我們將它設(shè)置為525336576字節(jié),也就是501M的大小限制妓美。
修改完以上前端和后端僵腺,提交修改的代碼到git上即可。
第三步:
Nginx配置
進入到項目部署發(fā)布所在的Linux下壶栋,進入nginx服務(wù)器所安裝的目錄辰如,
進入到nginx服務(wù)器所安裝的目錄
進入到nginx服務(wù)器目錄下的conf目錄
查看nginx.conf配置文件內(nèi)容中的client_max_body_size配置的大小,這里設(shè)置的是300M贵试。
使用vi或者vim打開nginx.conf配置文件琉兜,修改client_max_body_size的大小為501M,保存即可
進入到nginx服務(wù)器下的sbin目錄下毙玻,我們使用./nginx -t查看配置文件是否成功使用豌蟋,然后使用./nginx -s reload重啟Nginx服務(wù)器即可。
第四步:
Tomcat配置
由于項目使用的是Spring Cloud桑滩,自然使用Spring Boot梧疲,我們這個項目還是使用外置的Tomcat作為他的服務(wù)器,便于我們對Tomcat服務(wù)器進行優(yōu)化和設(shè)置。
進入到項目使用的Tomcat服務(wù)器的目錄
進入到指定項目使用的Tomcat服務(wù)器的目錄
進入到Tomcat服務(wù)器下的conf配置目錄中
看到server.xml配置文件后
先行查看Tomcat服務(wù)器的配置幌氮,其中兩個屬性對于這次是比較重要的一個是connectionTimeout這個連接超時時間設(shè)置以及默認的maxPostSize屬性的設(shè)置
使用vi或者vim打開server.xml配置文件缭受,修改connectionTimeout的大小為2000000,這個屬性的單位是毫秒浩销,換算之后大概是半個小時贯涎,我們配置缺省的maxPostSize屬性的值,默認情況下它的值是2097152慢洋,它的單位是字節(jié)塘雳,也就是2M的大小,修改完保存即可
修改完服務(wù)器之后普筹,使用發(fā)布工具重新從git上拉取最新的代碼和部署發(fā)布败明,重新啟動腳本即可完成修改,再次嘗試大文件上傳太防,功能基本實現(xiàn)妻顶。
以上需要注意的是maxPostSize屬性在各個Tomcat版本中的不同,源碼可以網(wǎng)上搜索“up6”
歡迎入群一起討論:374992201