JSF2.0简单文件输入

时间:2010-08-11 15:01:18

标签: jsf file-upload jsf-2

我正在尝试向我的webapp添加一个非常简单的文件输入,我正在使用JSF2.0和RichFaces 3.3.3,我真的不喜欢richfaces fileInput组件而且我正在寻找更简单的东西(在使用和外观方面),到目前为止我发现:

  • tomahawk的fileInput - 但是tomahawk只支持JSF1.2
  • trinidad fileInput - 但JSF2.0的trinidad处于alpha阶段
  • primefaces - 但当然它们不适用于RichFaces 3.3.3(只有4.0版处于测试阶段)

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

4 个答案:

答案 0 :(得分:1)

你基本上需要做两件事:

  1. 创建一个过滤器,将multipart/form-data项放在自定义地图中,并将原始请求参数映射替换为原始请求参数映射,以便正常request.getParameter()进程继续工作。

  2. 创建一个JSF 2.0自定义组件,该组件呈现input type="file"并且知道此自定义地图并可以从中获取上传的文件。

  3. @taher已经提供了一个链接,您可以在其中找到见解和代码段。 JSF 2.0片段应该是可重用的。您还必须修改MultipartMap以使用良好的'ol Apache Commons FileUpload API而不是Servlet 3.0 API。

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


    更新:我差点忘了你,我做了一个快速更新,用Commons 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.
        }
    
    }
    

    您仍然需要this article中所述的MultipartFilterMultipartRequest类。您只需删除@WebFilter注释,并在url-pattern /* <init-param>以及location {{1}}上映射过滤器,其中您指定绝对路径上传的文件将被存储。您可以使用JSF 2.0自定义文件上载组件,如this article中所述。

答案 1 :(得分:0)

亲爱的,您必须使用rich:uploadFile或通过http://balusc.blogspot.com/2009/12/uploading-files-with-jsf-20-and-servlet.html

在JSF中制作自定义组件

答案 2 :(得分:0)

在我尝试了tomahawk后,我提到它不适用于AJAX。所以我决定破解富文件: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是Add-Button的输入元素(type="file")。 invisibleClass应该只包含display:none;。使用style="display:none;"它将无效。

答案 3 :(得分: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);

 }