Загрузка файла JSF 2.0

Я просматриваю несколько блогов, чтобы попытаться найти, как загружать файлы с помощью JSF 2.0 Но все решения меня путают. Я хотел бы знать, что мне нужно, чтобы иметь возможность успешно загружать файл (MP3, PDF, видео... что когда-либо типа) и хранить его в базе данных в виде @Lob. Это то, что я сделал до сих пор:

  • Я создал объект, который имеет атрибут типа byte [], а также аннотируется аннотацией @Lob.

  • Я создал EJB, который представит сущность с помощью метода, который имеет байт [] в качестве параметра и вставляет его в базу данных, используя класс EntityManager (метод persist).

  • Я создал страницу JSF с тегом ввода типа "файл" и кнопкой отправки

  • Я подготовил управляемый bean для обмена информацией о файле со страницей JSF.

Теперь я застрял, и у меня много сомнений:

  • Что мне делать, чтобы передать файл из JSF в управляемый bean, а затем преобразовать его в байт [] (чтобы иметь возможность обрабатывать его в EJB)?

  • Как сервлет может мне помочь?

  • Мне нужен сервлет, чтобы сделать это?

  • Также я обнаружил, что в каком-то блоге упоминается что-то о сервлетах 3.0, но я не знаю, использует ли его рабочую среду, как это сделать, если я использую сервлеты 3.0 (я использую JEE6)?

Я никогда раньше не загружал файлы, а также не очень хорошо разбираюсь в сервлетах. Я смущен, кто-то может дать мне несколько советов, пожалуйста?

Ответ 1

Прежде всего, этот (старый) вопрос и ответ предполагает JSF 2.0/2.1. Поскольку в JSF 2.2 есть собственный <h:inputFile> компонент без необходимости в сторонних библиотеках компонентов. См. Также Как загрузить файл с помощью JSF 2.2 < h: inputFile > ? Где сохраненный файл?


Самый простой способ - использовать Tomahawk для JSF 2.0. Он предлагает компонент <t:inputFileUpload>.

Вот пошаговое руководство:

  • Создайте пустой динамический веб-проект для Servlet 3.0 и JSF 2.0. web.xml должен соответствовать спецификации Servlet 3.0 и уже содержать сервлет JSF:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app 
        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 http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
        id="YourProjectName" version="3.0">
    
        <display-name>Your Project Name</display-name>
    
        <servlet>
            <servlet-name>Faces Servlet</servlet-name>
            <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>Faces Servlet</servlet-name>
            <url-pattern>*.xhtml</url-pattern>
        </servlet-mapping>
    
    </web-app>
    

    faces-config.xml должен соответствовать спецификации JSF 2.0:

    <?xml version="1.0" encoding="UTF-8"?>
    <faces-config
        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 http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
        version="2.0">
    
    </faces-config>
    

  • Загрузите Tomahawk 1.1.10 для JSF 2.0. Извлеките zip файл, перейдите в папку /lib и скопируйте все *.jar файлы в /WEB-INF/lib.

    Это 18 файлов, из которых batik*.jar и xml*.jar не нужны для использования только компонента t:inputFileUpload. Вы можете оставить их.


  • Настройте фильтр расширений Tomahawk в web.xml. Это тот, кто отвечает за обработку запросов multipart/form-data, которые необходимы для отправки файлов через HTTP.

    <filter>
        <filter-name>MyFacesExtensionsFilter</filter-name>
        <filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>MyFacesExtensionsFilter</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
    </filter-mapping>
    

    Обратите внимание, что <servlet-name> должен соответствовать точной <servlet-name> FacesServlet, как вы определили в web.xml.


  • Создайте простой Facelet, upload.xhtml:

    <!DOCTYPE html>
    <html lang="en"
        xmlns="http://www.w3.org/1999/xhtml"
        xmlns:f="http://java.sun.com/jsf/core"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:t="http://myfaces.apache.org/tomahawk"
        xmlns:ui="http://java.sun.com/jsf/facelets">
        <h:head>
            <title>Tomahawk file upload demo</title>
        </h:head>
        <h:body>
            <h:form enctype="multipart/form-data">
                <t:inputFileUpload value="#{bean.uploadedFile}" />
                <h:commandButton value="submit" action="#{bean.submit}" />
                <h:messages />
            </h:form>
        </h:body> 
    </html>
    

    Обратите внимание на атрибут enctype="multipart/form-data" на <h:form>, это очень важно, чтобы отправлять файлы с HTTP.


  • Создайте простой управляемый bean, com.example.Bean:

    package com.example;
    
    import java.io.IOException;
    
    import javax.faces.application.FacesMessage;
    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.RequestScoped;
    import javax.faces.context.FacesContext;
    
    import org.apache.commons.io.FilenameUtils;
    import org.apache.myfaces.custom.fileupload.UploadedFile;
    
    @ManagedBean
    @RequestScoped
    public class Bean {
    
        private UploadedFile uploadedFile;
    
        public void submit() throws IOException {
            String fileName = FilenameUtils.getName(uploadedFile.getName());
            String contentType = uploadedFile.getContentType();
            byte[] bytes = uploadedFile.getBytes();
    
            // Now you can save bytes in DB (and also content type?)
    
            FacesContext.getCurrentInstance().addMessage(null, 
                new FacesMessage(String.format("File '%s' of type '%s' successfully uploaded!", fileName, contentType)));
        }
    
        public UploadedFile getUploadedFile() {
            return uploadedFile;
        }
    
        public void setUploadedFile(UploadedFile uploadedFile) {
            this.uploadedFile = uploadedFile;
        }
    
    }
    

Это должно быть так. Откройте его http://localhost:8080/projectname/upload.xhtml.

Что касается ваших конкретных вопросов:

что мне делать, чтобы передать файл из JSF в управляемый bean, а затем преобразовать его в байт [] (чтобы иметь возможность обрабатывать его в EJB)?

Об этом сказано выше.

Как сервлет может мне помочь?

Он способен обрабатывать и контролировать HTTP-запросы/ответы. В среде JSF FacesServlet уже выполняет всю работу.

Мне нужен сервлет, чтобы сделать это?

В среде JSF параметр FacesServlet является обязательным. Но он уже предоставлен API, вам не нужно писать его самостоятельно. Однако, чтобы иметь возможность загружать файлы из базы данных, другой сервлет определенно полезен. Здесь вы можете найти базовый пример: Servlet для обслуживания статического контента.

Также я обнаружил, что в каком-то блоге он упоминает что-то о сервлетах 3.0, но я не знаю, работает ли его рабочая среда, как можно, если я использую сервлеты 3.0 (я пользуюсь JEE6)?

Если вы используете контейнер Servlet 3.0, например Glassfish 3, JBoss AS 6, Tomcat 7 и т.д., а web.xml объявлен как Servlet 3.0, то вы определенно используете Servlet 3.0. Servlet 3.0 является частью Java EE 6.

Ответ 2

Для полноты я просто хочу предоставить полностью функциональный сам содержащийся пример того, как это делается с JSF 2.2, либо с запросами без Ajax и Ajax. Имейте в виду, что JSF 2.2 использует разные пространства имен, и вы должны работать с контейнером Servlet 3.0 (как Tomcat 7.0.x, JBoss AS 6.x и 7.x и GlassFish 3.x есть).

fileUpload.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head />
<h:body>
    <h:form enctype="multipart/form-data">
        <h:inputFile value="#{uploadBean.file}" />
        <h:commandButton value="Post Upload" action="#{uploadBean.upload}" />
    </h:form>
    <h:form enctype="multipart/form-data">
        <h:inputFile value="#{uploadBean.file}" />
        <h:commandButton value="Ajax Upload">
            <f:ajax listener="#{uploadBean.upload}" execute="@form"
                render="countOutput" />
        </h:commandButton>
    <!-- Counts the uploaded items -->
    <h:outputText id="countOutput"
        value="Files uploaded #{uploadBean.filesUploaded}" />
    </h:form>
</h:body>
</html>

UploadBean.java:

@ManagedBean
@ViewScoped
public class UploadBean {

    private int filesUploaded = 0;

    //javax.servlet.http.Part (Servlet 3.0 API)
    private Part file;
    private String fileContent;

    /**
     * Just prints out file content
     */
    public void upload() {
        try {
            fileContent = new Scanner(file.getInputStream())
                    .useDelimiter("\\A").next();
            System.out.println(fileContent + " uploaded");
            filesUploaded++;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public int getFilesUploaded() {
        return filesUploaded;
    }

    public Part getFile() {
        return file;
    }

    public void setFile(Part file) {
        this.file = file;
    }
}

См. также:

Ответ 4

Сообщение в блоге BalusC: Загрузка файлов с помощью JSF 2.0 и Servlet 3.0 - это то, что спасло меня, потому что у меня были проблемы с тегом RichFaces 4 fileUpload с Spring WebFlow.

Стоит изменить код BalusC на использование Spring MultipartResolver - вам не нужно его MultipartMap из другого сообщения в блоге.

Я достиг этого, изменив метод decode в FileRenderer следующим образом:

    UploadedFile ret = null;

    Object req = context.getExternalContext().getRequest();
    if (req instanceof MultipartHttpServletRequest) {
      MultipartFile file = ((MultipartHttpServletRequest)req).getFile(clientId);

      File temp = null;
      try {
        temp = File.createTempFile("_UPLOAD_", null);
        file.transferTo(temp);

        String name = new File(file.getOriginalFilename()).getName();
        ret = new UploadedFile(temp, name);

      } catch (IOException e) {
        throw new RuntimeException("Could not create temp file.", e);
      }
    } else {
      throw new IllegalStateException("Request is not multipart. Use spring multipart resolver.");
    }
    // If no file is specified, set empty String to trigger validators.
    ((UIInput) component).setSubmittedValue( ret == null ? EMPTY_STRING : ret);

A UploadedFile - это простой сериализуемый POJO, используемый для возврата результатов к поддержке bean.

Ответ 5

В JSF 2.2 вы можете легко загрузить файл с помощью тега без использования commons-io или filter. Этот тег поддерживает как обычный, так и ajax-процесс.

Обычный:

    <h:inputFile id="file"  value="#{fileUploadBean.uploadedFile}"/> 
    <h:commandButton id="button" action="#{fileUploadBean.sumbit()}" value="Upload"/>

Ajax:

    <h:inputFile id="file" value="#{fileUploadBean.uploadedFile}"/> 
    <h:commandButton id="button" value="submit">
      <f:ajax execute="@all" render="@all" onevent="statusUpdate"/>
    </h:commandButton>

Создайте управляемый bean следующим образом:

  @Named
  @RequestScoped
  public class FileUploadBean {

   private Part uploadedFile;

  }

Ответ 6

Самый простой способ - это, вероятно, использовать тег inputFileUpload, который вы можете найти в MyFaces:

http://myfaces.apache.org/

Ответ 7

IceFaces2.0 имеет один, http://wiki.icefaces.org/display/ICE/FileEntry Не пробовал реализовать его еще, но загрузка имеет примеры приложений и работает под Tomcat 6 (сервлет 2.5, а не JEE6)

Ответ 8

Вы должны добавить commons-fileupload-1.2.1.jar в наш проект "Путь сборки"

1.Сообщите файл web.xml:

Web.xml

    <filter>
        <filter-name>PrimeFaces FileUpload Filter</filter-name>
        <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>PrimeFaces FileUpload Filter</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
    </filter-mapping>
    <mime-mapping>        
        <extension>png</extension>
        <mime-type>image/png</mime-type>
    </mime-mapping>

2. Создать ManagedBean

   @ManagedBean
   @SessionScoped
public class FileUploadBean implements Serializable{
public FileUpload (){
}
  private StreamedContent file;
public void loadFile(FileUploadEvent event) throws IOException, InterruptedException {

        InputStream input = new ByteArrayInputStream(event.getFile().getContents());
        file= new DefaultStreamedContent(input, "image/jpg");
    }
}

Файл 3.jsf(xhtml)

   <h:form enctype="multipart/form-data"> 
         <p:fileUpload fileUploadListener="#{fileUploadBean.file}" sizeLimit="100000" allowTypes="/(\.|\/)(gif|jpe?g|png|bmp)$/"/>
        </h:form>