AJAX+JSF組件實現(xiàn)高性能的文件上載(4)
[@more@]
四、處理AJAX請求 AJAX請求的生成是在這個組件的解碼方法中處理的。我們需要檢查這是否是一個實際的AJAX請求(為了區(qū)別于正常的編譯行為),然后基于由ProgressMonitorFileItemFactory類的SessionUpdatingProgressObserver實例設置在會話中的值把一個XML響應發(fā)送回客戶端。
創(chuàng)新互聯(lián)是一家企業(yè)級云計算解決方案提供商,超15年IDC數(shù)據(jù)中心運營經(jīng)驗。主營GPU顯卡服務器,站群服務器,
溫江服務器托管,海外高防服務器,
服務器機柜,動態(tài)撥號VPS,海外云手機,海外云服務器,海外服務器租用托管等。
public void decode(FacesContext context, UIComponent component) { UIFileUpload input = (UIFileUpload) component; //檢查是否這是一個上傳進度請求,或是一個實際的上傳請求. ExternalContext extContext = context.getExternalContext(); Map parameterMap = extContext.getRequestParameterMap(); String clientId = input.getClientId(context); Map requestMap = extContext.getRequestParameterMap(); if(requestMap.get(clientId) == null){ return;//什么也不做,返回 } if(parameterMap.containsKey(PROGRESS_REQUEST_PARAM_NAME)){ //這是一個在該文件請求中的得到進度信息的請求. //得到該進度信息并把它生成為XML HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getResponse(); //設置響應的頭信息 response.setContentType("text/xml"); response.setHeader("Cache-Control", "no-cache"); try { ResponseWriter writer = FacesUtils.setupResponseWriter(context); writer.startElement("progress", input); writer.startElement("percentage", input); //從會話中獲得當前進度百分數(shù)(由過濾器所設置). Double progressCount = (Double)extContext.getSessionMap(). get("FileUpload.Progress." +input.getClientId(context)); if(progressCount != null){ writer.writeText(progressCount, null); }else{ writer.writeText("1", null);//我們還沒有收到上傳 } writer.endElement("percentage"); writer.startElement("clientId", input); writer.writeText(input.getClientId(context), null); writer.endElement("clientId"); writer.endElement("progress"); } catch(Exception e){ //做一些錯誤記錄... } }else{ //正常的譯碼請求. ...
|
五、 正常的譯碼行為
在正常的編譯期間,文件上傳生成器從請求屬性中檢索FileItem,正是在此處它被過濾器所設置,并且更新該組件的值綁定。然后,該會話中的進度被更新到100%,這樣在頁面上的JavaScript就可以把組件送入第3個階段。
//正常的譯碼請求. if(requestMap.get(clientId).toString().equals("file")){ try{ HttpServletRequest request = (HttpServletRequest)extContext.getRequest(); FileItem fileData = (FileItem)request.getAttribute(clientId); if(fileData != null) input.setSubmittedValue(fileData); //現(xiàn)在我們需要清除與該項相關的任何進度 extContext.getSessionMap().put( "FileUpload.Progress." + input.getClientId(context),new Double(100)); }catch(Exception e){ throw new RuntimeException("不能處理文件上傳" +" - 請配置過濾器.",e); } }
|
客戶端JavaScript負責向服務器發(fā)出進度請求并通過不同階段來移動組件。為了簡化處理所有的瀏覽器特定的XMLHttpRequest對象的問題,我選用了Matt Krause提供的AjaxRequest.js庫。該庫大限度地減少我們需要編寫的JavaScript代碼的數(shù)量,同時可以使這個組件正常工作。也許把這部分JavaScript代碼打包為該組件的一部分,然后從PhaseListener生成它更好一些,但是,我已經(jīng)通過定義一個到JSP頁面上的JavaScript庫的鏈接來盡力使得它簡單。
組件中的getProgressBarJavaScript方法被調用以生成JavaScript。使JavaScript正常工作通常是實現(xiàn)AJAX組件最困難的部分;不過我想,下面的代碼已經(jīng)非常清晰易于理解了。盡管在我的示例中JavaScript是嵌入到Java代碼中的,但是把它放到一個外部獨立的文件中也許更好一些。在本文中,我只是想使問題更為簡單些且只關心本文的主題。下面是一個將由組件生成的JavaScript的示例。其中假定,fileUpload1是被賦值到該文件組件的客戶端JSF Id,而uploadForm是HTML表單的Id。
function refreshProgress(){ // 假定我們正在進入到階段2. document.getElementById('fileUpload1_stage1').style.display = 'none'; document.getElementById('fileUpload1_stage2').style.display = ''; document.getElementById('fileUpload1_stage3').style.display = 'none'; //創(chuàng)建AJAX寄送 AjaxRequest.post( { //指定正確的參數(shù),以便 //該組件在服務器端被正確處理 'parameters':{ 'uploadForm':'uploadForm', 'fileUpload1':'fileUpload1', 'jsf.component.UIFileUpload':'1', 'ajax.abortPhase':'4' } //Abort at Phase 4. //指定成功處理相應的回調方法. ,'onSuccess':function(req) { var xml = req.responseXML; if( xml.getElementsByTagName('clientId').length == 0) { setTimeout('refreshProgress()',200); return; } var clientId = xml.getElementsByTagName('clientId'); clientId = clientId[0].firstChild.nodeValue + '_progressBar'; //從XML獲取百分比 var percentage = xml.getElementsByTagName('percentage')[0].firstChild.nodeValue; var innerSpans = document.getElementById(clientId).getElementsByTagName('span'); document.getElementById(clientId + 'label').innerHTML = Math.round(percentage) + '%'; //基于當前進度,設置這些span的式樣類。 for(var i=0;i<innerSpans.length;i++){ if(i < percentage){ innerSpans[i].className = 'active'; }else{ innerSpans[i].className = 'passive'; } } //如果進度不是100,我們需要繼續(xù)查詢服務器以實現(xiàn)更新. if(percentage != 100){ setTimeout('refreshProgress()',400); } else { //文件上傳已經(jīng)完成,我們現(xiàn)在需要把該組件送入到第3個階段. document.getElementById('fileUpload1_stage1').style.display = 'none'; document.getElementById('fileUpload1_stage2').style.display = 'none'; document.getElementById('fileUpload1_stage3').style.display = ''; } } }); } return builder.toString();
|
六、 結論
我很希望,本文能夠在有關如何使得文件上傳更具有用戶友好性,并且把AJAX和JavaServer Faces用于實現(xiàn)高級用戶接口組件的可能性方面引發(fā)你的進一步思考。毫無疑問,本文中的方案比較冗長并且有可能得到進一步的改進。我希望你能詳細地分析一下本文中所提供的完整的源代碼來深入理解本文中所討論的概念。
網(wǎng)頁題目:AJAX+JSF組件實現(xiàn)高性能的文件上載(4)-創(chuàng)新互聯(lián)
分享路徑:
http://weahome.cn/article/gihcj.html