0 Replies Latest reply on Feb 28, 2011 6:05 PM by t_guen03

    apache.commons.fileupload - Browser blocks ajax requests

    t_guen03

      Hi,

       

      its my first post here so far, I hope I do not ask this question in the wrong place. I hope you can help me with my problem.

      I want to have a progressbar at my page, which displays the status of a fileupload.

      Therefore I got a <h:form>-tag like this :

       

      <h:form id="uploadForm" target="iframe"
                  enctype="multipart/form-data">
                  <h:outputLabel 
                      styleClass="label" value="Select File"/>
                          <div class="round"><input name="file" type="file"/></div>
                  <h:commandButton name="upload" id="uploadbt"
                      action="#{uploadBean.upload}" value="Upload"
                      onclick="startPolling('uploadForm');">
                      </h:commandButton>
                      <div style="min-width: 400px; min-height: 22px; height: 22px; width: 400px;" id="progressbar">
                      <ui:repeat var="element" value="#{uploadBean.progressElements}">
                      <span class="progressActive" style="display: inline-block; min-width: 4px; min-height: 21px; height: 21px; width: 4px;"></span>
                      </ui:repeat>
                      <h:inputHidden value="#{uploadBean.finished}" id="flag" />
                      </div>
      </h:form>
      

       

      When the user clicks the commandButton the upload is started. On the server side the send request is wrapped and the request is parsed by a ServletFileUpload object. This looks like this:

       

      try{
      
                  ServletFileUpload upload = new ServletFileUpload();
                  upload.setFileSizeMax(maxFileSize);
                  upload.setFileItemFactory(new ProgressMonitorFileItemFactory(request, username));
      
                  ProgressListener progressListener = new SignalFinishProgressListener(request.getSession(), "FileUpload.Progress.finished");
                  upload.setProgressListener(progressListener);
      
                  @SuppressWarnings("all")
                  List fileItems = upload.parseRequest(request);
                  formParameters = new HashMap<String,String>();
                  fileParameters = new HashMap<String,FileItem>();    
      
                  for(int i=0;i<fileItems.size();i++){
                      FileItem item = (FileItem)fileItems.get(i);
                      if(item.isFormField() == true){
                          formParameters.put(item.getFieldName(),item.getString());
                      }else{
                          fileParameters.put(item.getFieldName(),item);   
                          request.setAttribute(item.getFieldName(),item);
                      }    
                  }
              }catch(FileUploadException fe){
                  fe.printStackTrace();
                  throw new UploadError(fe.getMessage());
              }catch(Exception ne){
                  ne.printStackTrace();
                  throw new RuntimeException(ne);
              } 
          }
      

       

      The installed ProgressListener just sets a sessionvariable called "FileUpload.Progress.finished" if the upload is ready. Furthermore the percentage of written bytes is stored in the session under the key "FileUpload.Progress.file" (You can't see it here, its done while writing the Fileitems to disk).

       

      There is also registered a onclick listener to the button, which starts the polling. It is sending an ajax.request to render the progressbar.

      The javascript looks like this :

       

      function startPolling(formid) {
          function poll(data){
              if(data.status == "success") {
                  alert('POLL');
                  var flag = document.getElementById(formid+':flag');
                  if(flag.value != "true") {
                      startPolling(formid);
                  }
              }
          }
          jsf.ajax.request(formid, null, {render: formid, onevent: poll});
      }
      

       

      Okay,we nearly got it : ) . Last there is the uploadBean.upload method :

       

      public void upload(){
              HttpSession session = (HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(false);
              status = (Double)session.getAttribute("FileUpload.Progress.file");
              if(status == null)
                  return;
              System.out.println("Percentage : " + status.intValue());
              for(int j = status.intValue() - progressElements.size(); j > 0; j--)
                  progressElements.add(new Byte((byte)0xff));
              if(session.getAttribute("FileUpload.Progress.finished") != null) {
                  for(int j = 100-progressElements.size(); j>0; j--)
                      progressElements.add(new Byte((byte)0xff));
                  finished = true;
              }
          }
      

       

      This method gets invoked before the page gets rendered. Thats because i registered a preRenderView event listener to the page. This means, that this method gets called after every send ajax request, which goes through the partial lifecycle to render the progressbar. The method eventually adds new Bytes to the progressElements list. The list gets used by the ui:repeat element to build the progressbar. Finally the method checks if the FileUpload.Progress.finished attribute was set by the ProgressListener, which we installed to the ServletFileUpload instance (you remember ? ; ) ).

      Ok, i hope you understood the set up. And now to my problem. When i upload a file, there are no ajax requests send, while uploading. The result is that my progressbar doesnt update itself.

       

      Do you know a workaround, or at least can tell me the reason of this ?