2010-08-11 112 views
2

我想添加一个非常简单的文件输入到我的webapp,我正在使用JSF2.0和RichFaces 3.3.3,事情是我真的不喜欢richfaces fileInput组件和我在找更简单的东西(在使用方面,看起来),到目前为止,我发现:JSF2.0简单文件输入

  • 战斧的的FileInput - 但战斧只支持JSF1.2
  • 特立尼达的FileInput - 但特立尼达JSF2.0是在alpha阶段
  • primefaces - 但他们当然不会使用RichFaces 3.3.3(只有4.0在测试版)

还有其他的选择吗?我需要一些非常简单的东西,比如普通的html文件输入组件。

回答

1

使自定义组件在JSF基本上,您需要做两件事情:

  1. 创建这使在multipart/form-data项的过滤器自定义映射并用它替换原始请求参数映射,以便正常request.getParameter()进程继续工作。

  2. 创建一个JSF 2.0自定义组件,它呈现input type="file"并知道此自定义映射并可以从其获取上传的文件。

@taher已经给出了一个链接,您可以在其中找到洞察和代码片段。 JSF 2.0片段应该是可重用的。您还必须修改MultipartMap才能使用良好的ol Apache Commons FileUpload API而不是Servlet 3.0 API。

如果我有时间,我会在一天结束时重写它并将其发布到此处。


更新:我几乎忘了你,我做了一个快速更新以取代通用FileUpload API的Servlet 3.0 API,它应该工作:

package net.balusc.http.multipart; 

import java.io.BufferedInputStream; 
import java.io.BufferedOutputStream; 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.util.Arrays; 
import java.util.Collections; 
import java.util.Enumeration; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.Map.Entry; 

import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.http.HttpServletRequest; 

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; 
import org.apache.commons.io.FilenameUtils; 
import org.apache.commons.io.IOUtils; 

public class MultipartMap extends HashMap<String, Object> { 

    // Constants ---------------------------------------------------------------------------------- 

    private static final String ATTRIBUTE_NAME = "parts"; 
    private static final String DEFAULT_ENCODING = "UTF-8"; 
    private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB. 

    // Vars --------------------------------------------------------------------------------------- 

    private String encoding; 
    private String location; 

    // Constructors ------------------------------------------------------------------------------- 

    /** 
    * Construct multipart map based on the given multipart request and file upload location. When 
    * the encoding is not specified in the given request, then it will default to <tt>UTF-8</tt>. 
    * @param multipartRequest The multipart request to construct the multipart map for. 
    * @param location The location to save uploaded files in. 
    * @throws ServletException If something fails at Servlet level. 
    * @throws IOException If something fails at I/O level. 
    */ 
    @SuppressWarnings("unchecked") // ServletFileUpload#parseRequest() isn't parameterized. 
    public MultipartMap(HttpServletRequest multipartRequest, String location) 
     throws ServletException, IOException 
    { 
     multipartRequest.setAttribute(ATTRIBUTE_NAME, this); 

     this.encoding = multipartRequest.getCharacterEncoding(); 
     if (this.encoding == null) { 
      multipartRequest.setCharacterEncoding(this.encoding = DEFAULT_ENCODING); 
     } 
     this.location = location; 

     try { 
      List<FileItem> parts = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(multipartRequest); 
      for (FileItem part : parts) { 
       if (part.isFormField()) { 
        processFormField(part); 
       } else if (!part.getName().isEmpty()) { 
        processFileField(part); 
       } 
      } 
     } catch (FileUploadException e) { 
      throw new ServletException("Parsing multipart/form-data request failed.", e); 
     } 
    } 

    // Actions ------------------------------------------------------------------------------------ 

    @Override 
    public Object get(Object key) { 
     Object value = super.get(key); 
     if (value instanceof String[]) { 
      String[] values = (String[]) value; 
      return values.length == 1 ? values[0] : Arrays.asList(values); 
     } else { 
      return value; // Can be File or null. 
     } 
    } 

    /** 
    * @see ServletRequest#getParameter(String) 
    * @throws IllegalArgumentException If this field is actually a File field. 
    */ 
    public String getParameter(String name) { 
     Object value = super.get(name); 
     if (value instanceof File) { 
      throw new IllegalArgumentException("This is a File field. Use #getFile() instead."); 
     } 
     String[] values = (String[]) value; 
     return values != null ? values[0] : null; 
    } 

    /** 
    * @see ServletRequest#getParameterValues(String) 
    * @throws IllegalArgumentException If this field is actually a File field. 
    */ 
    public String[] getParameterValues(String name) { 
     Object value = super.get(name); 
     if (value instanceof File) { 
      throw new IllegalArgumentException("This is a File field. Use #getFile() instead."); 
     } 
     return (String[]) value; 
    } 

    /** 
    * @see ServletRequest#getParameterNames() 
    */ 
    public Enumeration<String> getParameterNames() { 
     return Collections.enumeration(keySet()); 
    } 

    /** 
    * @see ServletRequest#getParameterMap() 
    */ 
    public Map<String, String[]> getParameterMap() { 
     Map<String, String[]> map = new HashMap<String, String[]>(); 
     for (Entry<String, Object> entry : entrySet()) { 
      Object value = entry.getValue(); 
      if (value instanceof String[]) { 
       map.put(entry.getKey(), (String[]) value); 
      } else { 
       map.put(entry.getKey(), new String[] { ((File) value).getName() }); 
      } 
     } 
     return map; 
    } 

    /** 
    * Returns uploaded file associated with given request parameter name. 
    * @param name Request parameter name to return the associated uploaded file for. 
    * @return Uploaded file associated with given request parameter name. 
    * @throws IllegalArgumentException If this field is actually a Text field. 
    */ 
    public File getFile(String name) { 
     Object value = super.get(name); 
     if (value instanceof String[]) { 
      throw new IllegalArgumentException("This is a Text field. Use #getParameter() instead."); 
     } 
     return (File) value; 
    } 

    // Helpers ------------------------------------------------------------------------------------ 

    /** 
    * Process given part as Text part. 
    */ 
    private void processFormField(FileItem part) { 
     String name = part.getFieldName(); 
     String[] values = (String[]) super.get(name); 

     if (values == null) { 
      // Not in parameter map yet, so add as new value. 
      put(name, new String[] { part.getString() }); 
     } else { 
      // Multiple field values, so add new value to existing array. 
      int length = values.length; 
      String[] newValues = new String[length + 1]; 
      System.arraycopy(values, 0, newValues, 0, length); 
      newValues[length] = part.getString(); 
      put(name, newValues); 
     } 
    } 

    /** 
    * Process given part as File part which is to be saved in temp dir with the given filename. 
    */ 
    private void processFileField(FileItem part) throws IOException { 

     // Get filename prefix (actual name) and suffix (extension). 
     String filename = FilenameUtils.getName(part.getName()); 
     String prefix = filename; 
     String suffix = ""; 
     if (filename.contains(".")) { 
      prefix = filename.substring(0, filename.lastIndexOf('.')); 
      suffix = filename.substring(filename.lastIndexOf('.')); 
     } 

     // Write uploaded file. 
     File file = File.createTempFile(prefix + "_", suffix, new File(location)); 
     InputStream input = null; 
     OutputStream output = null; 
     try { 
      input = new BufferedInputStream(part.getInputStream(), DEFAULT_BUFFER_SIZE); 
      output = new BufferedOutputStream(new FileOutputStream(file), DEFAULT_BUFFER_SIZE); 
      IOUtils.copy(input, output); 
     } finally { 
      IOUtils.closeQuietly(output); 
      IOUtils.closeQuietly(input); 
     } 

     put(part.getFieldName(), file); 
     part.delete(); // Cleanup temporary storage. 
    } 

} 

你仍然需要两个MultipartFilterMultipartRequestthis article中所述。您只需要删除@WebFilter注释,并将url-patternurl-pattern<init-param><init-param>映射到,其中您指定要存储上载文件的绝对路径。您可以使用未更改的this article中描述的JSF 2.0定制文件上载组件。

+0

感谢BalusC,如果你说用Apache Commons FileUpload替换MultipartMap,那么我想我会尝试一下! – 2010-08-12 22:17:03

+0

如果没有创建自定义组件,这可以做到吗?我更愿意使用jsf-2 api而不指定供应商,这似乎需要构建自定义组件,如[link](http://balusc.blogspot.com/2009/12/uploading- files-with-jsf-20-and-servlet.html) – 2011-05-03 09:18:48

+0

@Rasmus:是的,但你至少需要一个过滤器,将多部分部分作为请求参数。在不创建自定义组件的情况下,您自己负责收集并验证提交的值并更新模型值并调用任何侦听器。 – BalusC 2011-05-03 10:31:41

0

我也试过tomahawk后,我提到它不适用于AJAX。所以我决定破解rich:fileUpload并在a4j:commandButton上执行点击添加按钮。下面的代码:

<a4j:form id="myForm"> 
    <a4j:commandButton id="myButton" value="Upload" title="Upload" styleClass="myButtonClass" 
        onclick="document.getElementById('myForm:myFileUpload:file').click()/> 

    <rich:fileUpload id="myFileUpload" maxFilesQuantity="1" autoclear="true" 
        immediateUpload="true" styleClass="invisibleClass" 
        fileUploadListener="#{uploadBean.uploadListener}"/> 
</a4j:form> 

myForm:myFileUpload:file是输入元素(type="file")的附加按钮。 invisibleClass应该只包含display:none;。随着style="display:none;"它不会工作。

0
You can used rich faces 3.3.3 file upload. 

步骤1:fileUpload.xhtml

<rich:fileUpload id="fileupload" addControlLabel="Browse" 
               required="true" 
               fileUploadListener="#{testForm.listener}" 
               acceptedTypes="xml" 
               ontyperejected="alert('Only xml files are accepted');" 
               maxFilesQuantity="1" listHeight="57px" listWidth="100%" 
               disabled="#{testForm..disabled}" > 
               <a4j:support event="onclear" 
                action="#{testForm..clearUploadData}" 
                reRender="fileupload" /> 
              </rich:fileUpload> 

步骤2:FileUpload.java

public class FileUpload implements Serializable{ 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 
    private String Name; 
    private String mime; 
    private long length; 
    private byte [] file; 
    private String absolutePath; 

    public String getName() { 
     return Name; 
    } 

    /** 
    * @return the file 
    */ 
    public byte[] getFile() { 
     return file; 
    } 

    /** 
    * @param file the file to set 
    */ 
    public void setFile(byte[] file) { 
     this.file = file; 
    } 

    /** 
    * @param mime the mime to set 
    */ 
    public void setMime(String mime) { 
     this.mime = mime; 
    } 
    public void setName(String name) { 
     Name = name; 
     int extDot = name.lastIndexOf('.'); 
     if(extDot > 0){ 
      String extension = name.substring(extDot +1); 
      if("txt".equals(extension)){ 
       mime="txt"; 
      } else if("xml".equals(extension)){ 
       mime="xml"; 

      } else { 
       mime = "unknown file"; 
      } 
     } 
    } 
    public long getLength() { 
     return length; 
    } 
    public void setLength(long length) { 
     this.length = length; 
    } 

    public String getMime(){ 
     return mime; 
    } 

    /** 
    * @return the absolutePath 
    */ 
    public String getAbsolutePath() { 
     return absolutePath; 
    } 

    /** 
    * @param absolutePath the absolutePath to set 
    */ 
    public void setAbsolutePath(String absolutePath) { 
     this.absolutePath = absolutePath; 
    } 
} 

步骤3:TESTFORM //调用听者

/** 
* 
* @param event 
* @throws Exception 
*/ 
public void listener(UploadEvent event) throws Exception{ 
     UploadItem item = event.getUploadItem(); 
     FileUpload file = new FileUpload(); 
     file.setLength(item.getData().length); 
     file.setFile(item.getData()); 
     file.setName(item.getFileName()); 
     files.add(file); 

} 
+0

你读过这个问题了吗? OP明确表示他不想使用它。 – BalusC 2014-02-05 09:16:44