3

在我当前的项目中,我正在尝试创建一个文件上传自定义组件,因为我们有一个不能使用任何组件库的约束。我们的要求是创建单个文件上传,在选择并上传文件后,它将显示在该组件下方的数据表中。用户将能够下载上传的文件,如果需要也可以删除上传的文件。将有一个 ajax 加载器,需要在上传文件时触发。图形用户界面看起来像这样。

 ________________________ __________  ____________
|                       | | Browse  | | Upload    |
|_______________________| |_________| |___________|

______________________________________________
|                                      |      |
|  File1.pdf                            |  *  |
|_______________________________________|_____|
|                                       |     |
|   File2.pdf                           |  *  |
|_______________________________________|_____|

为了创建这个组件,我在 Core JavaServer Pages(3e) 的帮助下创建了自定义组件和 BalusC 的博客,以触发来自 jsf 页面的 ajax 调用 (jsf.ajax.addOnEvent)。下面是 Renderer、xhtml 和 managedbean 的完整代码。目前我使用 ah:outputtext 而不是 h:datatable 来更新页面。

     <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:corejsf="http://corejsf.com">
     <h:head>
    <title>A file upload test</title>
        <h:outputScript name="jsf.js" library="javax.faces" target="head"/>
        <script>
             jsf.ajax.addOnEvent(function(data) {
                var ajaxstatus = data.status; 
                var ajaxloader = document.getElementById("ajaxloader");

                switch (ajaxstatus) {
                case "begin": // This is called right before ajax request is been sent.
                    ajaxloader.style.display = 'block';
                    break;

                case "complete":
                    ajaxloader.style.display = 'none';
                    break;

                case "success":                 // NOOP.
                     break;
             } });
    </script>
      </h:head>
      <h:body>
       <h:form>
            <h:commandButton value="hello"></h:commandButton>
       </h:form>
        <h:form enctype="multipart/form-data">
              Upload a photo of yourself: 
              <corejsf:upload uploadButton="upload"/>
              <h:outputText id="updateText" value="#{user.value}"></h:outputText>
            <h:commandButton action="#{user.submit}" value="Initiate"></h:commandButton>
             </h:form>
                <img id="ajaxloader" src="ajax-loader.gif" style="display: none;" />
        </h:body>
     </html>

渲染器:

  package com.corejsf;

  import java.io.File;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.UnsupportedEncodingException;
  import java.util.Map;

  import javax.el.ELContext;
  import javax.el.ValueExpression;
  import javax.faces.FacesException;
  import javax.faces.application.ResourceDependencies;
  import javax.faces.application.ResourceDependency;
  import javax.faces.component.EditableValueHolder;
  import javax.faces.component.UIComponent;
  import javax.faces.component.UIForm;
  import javax.faces.context.ExternalContext;
  import javax.faces.context.FacesContext;
  import javax.faces.context.ResponseWriter;
  import javax.faces.render.FacesRenderer;
  import javax.faces.render.Renderer;
  import javax.servlet.ServletContext;
  import javax.servlet.http.HttpServletRequest;
  import org.apache.commons.fileupload.FileItem;

  @FacesRenderer(componentFamily="javax.faces.Input",
      rendererType="com.corejsf.Upload")
   public class UploadRenderer extends Renderer {
        public void encodeBegin(FacesContext context, UIComponent component)  
            throws IOException {
         if (!component.isRendered()) return;
         ResponseWriter writer = context.getResponseWriter();
         String ajax = "jsf.ajax.request(this, event,{render:'j_idt11:updateText'}); return false";
         String clientId = component.getClientId(context);
         System.out.println("parentid>>>>>>"+component.getParent().getClientId(context));
         System.out.println(clientId);
         System.out.println("upload button >>>>>>"+(String)component.getAttributes().get("uploadButton"));
          writer.startElement("input", component);
         writer.writeAttribute("type", "file", "type");
         writer.writeAttribute("name", clientId+":INPUT_FILE", "clientId");
         writer.endElement("input");
         writer.startElement("input", component);
         writer.writeAttribute("type", "submit", null);
         writer.writeAttribute("name", clientId + ":FILE_UPLOAD", null);
         writer.writeAttribute("value", "Upload", "value");
         writer.writeAttribute("onclick", ajax, null);
         writer.endElement("input");
         writer.flush();
    }

    public void decode(FacesContext context, UIComponent component) {



   Map<String,String> requestMap = context.getExternalContext ().getRequestParameterMap();
   String clientId = component.getClientId(context);
   System.out.println("getId>>>>>>>"+component.getId());
   if(requestMap.containsKey(clientId+":FILE_UPLOAD")){

       try {
        Thread.sleep(4000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
       System.out.println("true");
       ExternalContext external = context.getExternalContext();
       HttpServletRequest request = (HttpServletRequest) external.getRequest();
       //String clientIdFile = component.getClientId(context);
       FileItem item = (FileItem) request.getAttribute(clientId+":INPUT_FILE");
       System.out.println("filename>>>>"+item.getName()+">>>");
       System.out.println("file blank>>>>"+item.getName().equals(""));
       ELContext elContext = FacesContext.getCurrentInstance().getELContext();
        UserBean userBean = (UserBean) FacesContext.getCurrentInstance().getApplication()
        .getELResolver().getValue(elContext, null, "user");
        try {
            userBean.setUploadedFile(item.getInputStream());
            userBean.setValue(userBean.getUploadedFileList().size());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
   }
   else
       System.out.println("false");
     }   
  }

托管豆:

  package com.corejsf;

  import java.io.Serializable;

  import javax.el.ELContext;
  import javax.faces.bean.ManagedBean; 
  //import javax.faces.bean.SessionScoped;
  import javax.faces.bean.ViewScoped;
  import javax.faces.context.FacesContext;
  import javax.faces.event.ActionEvent;
  import javax.faces.event.AjaxBehaviorEvent;

  import java.io.InputStream;
  import java.util.ArrayList;

  @ManagedBean(name="user")
  @ViewScoped
  public class UserBean implements Serializable {

private static final long serialVersionUID = 1L;
private String id;
private ArrayList<InputStream> uploadedFileList = new ArrayList<InputStream>();

public ArrayList<InputStream> getUploadedFileList() {
    return uploadedFileList;
}
public void setUploadedFileList(ArrayList<InputStream> uploadedFileList) {
    this.uploadedFileList = uploadedFileList;
}
private int value = 0;

public int getValue() {
    return value;
}
public void setValue(int value) {
    this.value = value;
}
public String getId() { return id; }
public void setId(String newValue) { id = newValue; }

public void setUploadedFile(InputStream inputStream){
    uploadedFileList.add(inputStream);
}
  }

上传过滤器:

   package com.corejsf;

   import java.io.File;
   import java.io.IOException;
   import java.util.Collections;
   import java.util.Enumeration;
   import java.util.HashMap;
   import java.util.List;
   import java.util.Map;
   import javax.servlet.Filter;
   import javax.servlet.FilterChain;
   import javax.servlet.FilterConfig;
   import javax.servlet.ServletException;
   import javax.servlet.ServletRequest;
   import javax.servlet.ServletResponse;
   import javax.servlet.http.HttpServletRequest;
   import javax.servlet.http.HttpServletRequestWrapper;
   import org.apache.commons.fileupload.FileItem;
   import org.apache.commons.fileupload.FileUploadException;
   import org.apache.commons.fileupload.disk.DiskFileItemFactory;
   import org.apache.commons.fileupload.servlet.ServletFileUpload;

    public class UploadFilter implements Filter {
        private int sizeThreshold = -1;
        private String repositoryPath;

        public void init(FilterConfig config) throws ServletException {
           repositoryPath = config.getInitParameter(
              "com.corejsf.UploadFilter.repositoryPath");
           try {
           String paramValue = config.getInitParameter(
               "com.corejsf.UploadFilter.sizeThreshold");
           if (paramValue != null) 
               sizeThreshold = Integer.parseInt(paramValue);
           }
           catch (NumberFormatException ex) {
               ServletException servletEx = new ServletException();
               servletEx.initCause(ex);
               throw servletEx;
           }
        }

         public void destroy() {
         }

 public void doFilter(ServletRequest request, 
  ServletResponse response, FilterChain chain) 
  throws IOException, ServletException {

  if (!(request instanceof HttpServletRequest)) {
     chain.doFilter(request, response);
     return;
  }

  HttpServletRequest httpRequest = (HttpServletRequest) request;

  boolean isMultipartContent 
     = ServletFileUpload.isMultipartContent(httpRequest);
  if (!isMultipartContent) {
     chain.doFilter(request, response);
     return;
  }

  DiskFileItemFactory factory = new DiskFileItemFactory();
  if (sizeThreshold >= 0)
     factory.setSizeThreshold(sizeThreshold);
  if (repositoryPath != null) 
     factory.setRepository(new File(repositoryPath));
  ServletFileUpload upload = new ServletFileUpload(factory);

  try {
     @SuppressWarnings("unchecked") List<FileItem> items 
        = (List<FileItem>) upload.parseRequest(httpRequest);
     final Map<String, String[]> map = new HashMap<String, String[]>();
     for (FileItem item : items) {
        String str = item.getString();
        if (item.isFormField())
           map.put(item.getFieldName(), new String[] { str });
        else
           httpRequest.setAttribute(item.getFieldName(), item);
     }

     chain.doFilter(new 
        HttpServletRequestWrapper(httpRequest) {
           public Map<String, String[]> getParameterMap() {
              return map;
           }                   
           // busywork follows ... should have been part of the wrapper
           public String[] getParameterValues(String name) {
              Map<String, String[]> map = getParameterMap();
              return (String[]) map.get(name);
           }
           public String getParameter(String name) {
              String[] params = getParameterValues(name);
              if (params == null) return null;
              return params[0];
           }
           public Enumeration<String> getParameterNames() {
              Map<String, String[]> map = getParameterMap();
              return Collections.enumeration(map.keySet());
           }
        }, response);
  } catch (FileUploadException ex) {
     ServletException servletEx = new ServletException();
     servletEx.initCause(ex);
     throw servletEx;
  }      
 }   
}

标签库.xml:

<facelet-taglib version="2.0"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee">
    <namespace>http://corejsf.com</namespace>
    <tag>
       <tag-name>upload</tag-name>
       <component>
           <component-type>javax.faces.Input</component-type>
           <renderer-type>com.corejsf.Upload</renderer-type>
       </component>
    </tag>
 </facelet-taglib>

我在使用此代码时面临的问题是 ajax 正在更新 h:outputtext 但 ajax 加载器无法正常工作。上传文件时不显示。它应该在开始状态下显示并在完成状态下消失。此外,firefox 错误控制台显示“参考错误:jsf 未定义”消息。

我放了一个:

<h:outputScript name="jsf.js" library="javax.faces" target="head"/> 

在 h:head 标签内。但这并没有帮助。在 Firefox 中添加此行后,网页没有响应,但它在 IE 上运行,尽管 ajax 加载器在任何情况下都不起作用。

请帮忙。

提前致谢。

4

0 回答 0