struts2 上傳文件添加進度條

爲了給用戶更好體驗,最進在struts2添加了上傳進度條讓用戶知道上傳過程時間,增長有好度。javascript

因爲之前作個 文件上傳 沒有用過 組件進行解析,直接用servlet 解析的,而如今 struts2 框架使用 commons-fileupload 解析上傳文件.css

一般咱們在action  中聲明 file,fileType,等字段  struts2 在執行action 方法時已經把 文件上傳解析好了。進行封裝後 傳到 action, 經過因此沒法在action 作文件解析監聽.html

struts2 上傳原理form中設定的提交內容是二進制格式的,Dispatcher類的wrapRequest方法會將請求交由實現MultiPartRequest接口的JakartaMultiPartRequestjava

類來處理jquery

在Struts2的JakartaMultiPartRequest類實現了MultiPartRequestWrapper接口, 裏面的parse方法中才會真正來調用commons-fileupload組件的 ServletFileUpload類對請求進行解析,最後進行封裝傳入action.ajax

知道原理後,思路也就清晰了。須要監聽上傳文件,則須要在這動文章.apache

首先須要在上傳文件頁面post提交文件, 在commons-fileupload 解析文件時,把解過程存入session, 而後在提交頁面用ajax 請求另外一個連接,讀出session裏面的 解析信息。顯示在頁面。json

提交頁面瀏覽器

  
1 < style type ="text/css" > 2 #progressBar { width : 400px ; height : 12px ; background : #FFFFFF ; border : 1px solid #000000 ; padding : 1px ; } 3 #progressBarItem { width : 30% ; height : 100% ; background : #FF0000 } 4 </ style > 5 < script type ="text/javascript" src ="js/jquery.js" ></ script > 6 < script type ="text/javascript" language ="javascript" > 7 var finished = true ; // 上傳是否結束 8 function showStatus(){ 9 finished = false ; 10 $( ' #progressBarItem ' ).attr( ' width ' , ' 1% ' ); 11 setTimeout( ' callback() ' , 1000 ); 12 } 13 14 function callback(){ 15 if (finished) return ; 16 var url = ' paper/doFileProgress ' ; 17 var jv = ajaxGetReq(url); 18 alert(jv); 19 setTimeout( ' callback() ' , 1000 ); 20 } 21 </ script > 22 </ head > 23 < body > 24 < iframe name ="upload_iframe" width ="0" height ="0" ></ iframe > 25 < div id ="progressBar" >< div id ="progressBarItem" ></ div ></ div >< div id ="statusInfo" ></ div > 26 < form id ="form1" method ="post" action ="paper/addPaper" enctype ="multipart/form-data" target ="upload_iframe" onsubmit ="return showStatus()" > 27 < input type ="file" name ="file1" />< br /> 28 < input type ="file" name ="file2" />< br /> 29 </ form > 30 </ body >

target 屬性默認是_self, 若是target 爲默認值,則提交後的新頁面會在當前窗口顯示,形成當前窗口短暫地白屏。在頁面添加一個隱藏iframe,把target屬性指定爲iframe,因此上傳文件 當前頁面看不來變化緩存

UploadSatatus.java 顯示狀態類

  
1 public class UploadStatus { 2 3 private long bytesRead; // 已經上傳的字節數,單位:字節 4 private long contentLength; // 全部文件的總長度,單位:字節 5 private int items; // 正在上傳第幾個文件 6 private long startTime = System.currentTimeMillis(); // 開始上傳的時間,用於計算上傳速度等 7 }

UploadListener.java 監聽類

  
1 public class UploadListener implements ProgressListener{ 2 3 private UploadStatus status; 4 5 public UploadListener(UploadStatus status){ 6 this.status = status; 7 } 8 9 10 public void update(long bytesRead, long contentLength, int items) { 11 //上傳組件會調用該方法 12 status.setBytesRead(bytesRead); //已讀取的數據長度 13 status.setContentLength(contentLength); //文件總長度 14 status.setItems(items); //正在保存第幾個文件 15 16 }

接下來 實現 struts2 2.3 版本 MultiPartRequest接口,  把

public class RefactorMultiPartRequest implements MultiPartRequest

複製一份JakartaMultiPartRequest類裏面的類代碼到 本身新建RefactorMultiPartRequest 類,同時修改parseRequest代碼(繼承JakartaMultiPartRequest也能夠,因爲這類裏私有方法太多,不適合繼承)

  
1 private List < FileItem > parseRequest(HttpServletRequest servletRequest, String saveDir) throws FileUploadException { 2 3 UploadStatus status = new UploadStatus(); // 上傳狀態 4 UploadListener listner = new UploadListener(status); // 監聽器 5 servletRequest.getSession().setAttribute( " uploadStatus " , status); // 把狀態放到session裏去 6 7 8 DiskFileItemFactory fac = createDiskFileItemFactory(saveDir); 9 ServletFileUpload upload = new ServletFileUpload(fac); 10 upload.setSizeMax(maxSize); 11 upload.setProgressListener(listner); // 添加監聽器 12 13 return upload.parseRequest(createRequestContext(servletRequest)); 14 }

在struts.xml裏面加入覆蓋JakartaMultiPartRequest類配置

  
1 < bean type ="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name ="refactor" 2 class ="org.scirp.common.interceptor.RefactorMultiPartRequest" scope ="default" /> 3 4 < constant name ="struts.multipart.handler" value ="refactor" />

至於我怎麼知道的,我也是閱讀了人家文章 strut2 內部原理 , 不過我覆蓋失敗),調試仍是調用原來的JakartaMultiPartRequest類,而不是調用我寫的RefactorMultiPartRequest (如今還沒解決,不知道是否是少寫了配置,我解決方法是 在我項目裏新建了一個包路徑和JakartaMultiPartRequest如出一轍的類,由於jdk 在相同包 java 文件時,會優先調用項目裏的類)

而後新建一個讀取進度方法

  
1 /** 2 * 顯示文件上傳的進度 3 */ 4 public void doFileProgress(){ 5 response.setHeader( " Cache-Control " , " no-store " ); // 禁止瀏覽器緩存 6 response.setHeader( " Pragrma " , " no-cache " ); // 禁止瀏覽器緩存 7 response.setDateHeader( " Expires " , 0 ); // 禁止瀏覽器緩存 8 9 UploadStatus status = (UploadStatus)session.getAttribute(ConfigKeys.UPLOAD_STATENAME); 10 if (status == null ){ 11 renderText( " error " ); 12 return ; 13 } 14 15 long startTime = status.getStartTime(); // 上傳開始時間 16 long currentTime = System.currentTimeMillis(); // 如今時間 17 long time = (currentTime - startTime) / 1000 + 1 ; // 已傳輸的時間 單位:s 18 19 // 傳輸速度單位:byte/s 20 double velocity = (( double )status.getBytesRead()) / ( double )time; 21 // 估計總時間 22 double totalTime = status.getContentLength(); 23 // 估計剩餘時間 24 double timeLeft = totalTime - time; 25 // 已經完成的百分比 26 int percent = ( int )( 100 * ( double )status.getBytesRead() / ( double )status.getContentLength()); 27 // 已經完成數單位:m 28 double length = (( double ) status.getBytesRead()) / 1024 / 1024 ; 29 // 總長度 單位:m 30 double totalLength = (( double ) status.getContentLength()) / 1024 / 1024 ; 31 32 // 我用的是json 33 JSONObject json = new JSONObject(); 34 json.put( " percent " , percent); 35 json.put( " length " , length); 36 json.put( " totalLength " , totalLength); 37 json.put( " velocity " , velocity); 38 json.put( " time " , time); 39 json.put( " totalTime " , totalTime); 40 json.put( " timeLeft " , timeLeft); 41 json.put( " fileNumber " , status.getItems()); 42 System.out.println(json.toString()); 43 renderText(json.toString()); 44 45 }

運行後

1

2

相關文章
相關標籤/搜索