2010-08-11 2 views
2

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

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

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

ответ

1

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

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

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

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

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


Update: Я чуть не забыл тебя, я сделал быстрое обновление, чтобы заменить 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 классов, как описано в this article. Вам нужно только удалить аннотацию @WebFilter и отобразить фильтр по адресу url-pattern из /*, а также <init-param> из location, в котором указывается абсолютный путь, в котором должны храниться загруженные файлы. Вы можете использовать компонент загрузки пользовательских файлов JSF 2.0, как описано в this article без изменений.

+0

Спасибо BalusC, если вы скажете, что замена MultipartMap на Apache Commons FileUpload будет работать, я думаю, я попробую! –

+0

Можно ли обойтись без создания пользовательского компонента? Я бы предпочел использовать jsf-2 api без указания поставщика, который, как казалось, должен был создать пользовательский компонент, как описано в вашем блоге по ссылке [http://balusc.blogspot.com/2009/12/uploading- files-with-jsf-20-and-servlet.html) –

+0

@Rasmus: Да, но вам нужен, по крайней мере, фильтр, который возвращает многочастные части в качестве параметров запроса. Без создания настраиваемого компонента вы сами несете ответственность за сбор и проверку представленного значения и обновление значения модели и вызов любого слушателя. – BalusC

0

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

+0

Проблема здесь что я использую Tomcat 6, который не поддерживает Servlet 3.0 (и это не мой призыв перейти на tomcat 7). –

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 является входом-Element (type="file") для Add-Button. 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

Вы прочитали вопрос? ОП четко заявил, что он не хотел этого использовать. – BalusC