Загрузка файла 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;
}
}
См. также:
Ответ 3
Я бы рекомендовал использовать сопутствующую библиотеку, например Tomahawk <t:inputFileUpload>
или PrimeFaces <p:fileUpload>
.
BalusC также имеет хорошее сообщение в блоге о Загрузка файлов с помощью JSF 2.0 и Servlet 3.0.
Ответ 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>