JSF2.0 простой ввод файла - PullRequest
2 голосов
/ 11 августа 2010

Я пытаюсь добавить очень простой ввод файла в мое веб-приложение, которое я делаю с использованием JSF2.0 и RichFaces 3.3.3, дело в том, что мне действительно не нравится компонент fileInput richfaces, и я ищу что-то более простое (с точки зрения использования и внешнего вида), до сих пор я нашел:

  • вход файла томагавка - но томагавк поддерживает только JSF1.2
  • Тринидад fileInput - но Тринидад для JSF2.0 находится в альфа-стадии
  • простые лица - но, конечно, они не будут работать с RichFaces 3.3.3 (только 4.0, которые находятся в бета-версии)

Есть ли другие варианты? Мне нужно что-то действительно простое, как обычный компонент ввода файла HTML.

Ответы [ 4 ]

1 голос
/ 12 августа 2010

Вам нужно сделать две вещи:

  1. Создайте фильтр, который помещает элементы multipart/form-data в пользовательскую карту и заменит им исходную карту параметров запроса, чтобы обычный процесс request.getParameter() продолжал работать.

  2. Создайте пользовательский компонент JSF 2.0, который отображает input type="file" и знает об этой пользовательской карте и может получать из нее загруженные файлы.

@ Тахер уже дал ссылку, где вы можете найти идеи и фрагменты кода. Фрагменты JSF 2.0 следует использовать повторно. Вам еще нужно изменить MultipartMap, чтобы использовать хороший API-интерфейс Apache Commons FileUpload вместо 'API Servlet 3.0.

Если у меня будет время, я к концу дня перепишу его и опубликую здесь.


Обновление : Я чуть не забыл вас, я сделал быстрое обновление, чтобы заменить Servlet 3.0 API Commons FileUpload 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.
    }

}

Вам по-прежнему нужны классы MultipartFilter и MultipartRequest, как описано в этой статье . Вам нужно только удалить аннотацию @WebFilter и сопоставить фильтр с url-pattern из /* вместе с <init-param> из location, в котором вы указываете абсолютный путь для хранения загруженных файлов. Вы можете использовать пользовательский компонент загрузки файлов JSF 2.0, как описано в этой статье без изменений.

0 голосов
/ 05 февраля 2014
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 голосов
/ 03 февраля 2012

После того, как я попробовал томагавк, я упомянул, что он не работает с 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 голосов
/ 12 августа 2010

Уважаемый, вы должны использовать rich: uploadFile или создать пользовательский компонент в JSF, выполнив http://balusc.blogspot.com/2009/12/uploading-files-with-jsf-20-and-servlet.html

...