fileupload - jsf subir archivos
Carga de archivo JSF 2.0 (8)
Estoy buscando en algunos blogs, para tratar de encontrar cómo subir archivos usando JSF 2.0. Pero todas las soluciones me confunden. Me gustaría saber qué es exactamente lo que necesito para poder subir un archivo (MP3, PDF, video ... cualquier tipo) y almacenarlo en una base de datos como @Lob. Esto es lo que he hecho hasta ahora:
Creé una entidad que tiene un atributo de tipo byte [] y también está anotado con una anotación @Lob.
Creé un EJB que introducirá la entidad con un método que tiene un byte [] como parámetro y lo inserta en la base de datos utilizando la clase EntityManager (método de persistencia).
Creé una página JSF con una etiqueta de entrada de tipo "archivo" y un botón de enviar
Preparé un frijol administrado para intercambiar información sobre el archivo con la página JSF.
Ahora estoy atascado, y tengo muchas dudas:
¿Qué debo hacer para pasar el archivo de JSF al bean administrado y luego transformarlo en un byte [] (Para poder manejarlo en el EJB)?
¿Cómo puede ayudarme un servlet?
¿Necesito un servlet para hacer esto?
También encontré que en algún blog menciona algo acerca de servlets 3.0, pero no sé si mi entorno de trabajo lo está usando, ¿cómo puedo hacerlo si estoy usando servlets 3.0 (estoy usando JEE6)?
Nunca cargué archivos antes y tampoco estoy muy familiarizado con los servlets. Estoy confundido, alguien podría darme algunos consejos de inicio, por favor?
Debe agregar commons-fileupload-1.2.1.jar
en nuestro proyecto Build Path
1.Configurar el archivo 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. Crear 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");
}
}
Archivo 3.jsf (xhtml)
<h:form enctype="multipart/form-data">
<p:fileUpload fileUploadListener="#{fileUploadBean.file}" sizeLimit="100000" allowTypes="/(/.|//)(gif|jpe?g|png|bmp)$/"/>
</h:form>
En JSF 2.2 puede cargar fácilmente archivos usando tag sin usar commons-io o filter. Esta etiqueta admite tanto el proceso normal como el ajax.
Normal:
<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>
Diseña tu bean administrado de la siguiente manera:
@Named
@RequestScoped
public class FileUploadBean {
private Part uploadedFile;
}
IceFaces2.0 tiene uno, http://wiki.icefaces.org/display/ICE/FileEntry No ha intentado implementarlo todavía, pero la descarga tiene aplicaciones de ejemplo y funciona bajo Tomcat 6 (servlet 2.5, entonces no JEE6)
La forma más fácil es, probablemente, utilizar la etiqueta inputFileUpload que puedes encontrar en MyFaces:
Para completar, solo deseo proporcionar un ejemplo autónomo completamente funcional de cómo se hace esto con JSF 2.2, ya sea con solicitudes que no sean Ajax o Ajax . Tenga en cuenta que JSF 2.2 usa diferentes espacios de nombres y necesita trabajar con un contenedor Servlet 3.0 (como Tomcat 7.0.x, JBoss AS 6.x y 7.x y 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;
}
}
Ver también:
Publicación de blog de BalusC: la carga de archivos con JSF 2.0 y Servlet 3.0 es lo que me salvó, porque tuve problemas al ejecutar RichFaces 4 fileUpload tag con Spring WebFlow.
Vale la pena modificar el código de BalusC para usar Springpart MultipartResolver
; no necesita su MultipartMap
de otra publicación de blog .
Lo logré modificando un método de decode
en FileRenderer
así:
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''s multipart resolver.");
}
// If no file is specified, set empty String to trigger validators.
((UIInput) component).setSubmittedValue( ret == null ? EMPTY_STRING : ret);
Un UploadedFile
es un POJO serializable simple usado para devolver resultados al bean de respaldo.
Yo recomendaría usar una biblioteca companent como <t:inputFileUpload> o PrimeFaces <p:fileUpload>
.
BalusC también tiene una buena publicación en el blog sobre la carga de archivos con JSF 2.0 y Servlet 3.0.
En primer lugar, esta (antigua) pregunta y respuesta asume JSF 2.0 / 2.1. Desde JSF 2.2 hay un componente nativo <h:inputFile>
sin necesidad de bibliotecas de componentes de terceros. Consulte también Cómo subir archivos usando JSF 2.2 <h: inputFile>? ¿Dónde está el archivo guardado?
La forma más fácil sería usar Tomahawk para JSF 2.0 . Ofrece un componente <t:inputFileUpload>
.
Aquí hay un tutorial paso a paso:
Cree un proyecto web dinámico en blanco para Servlet 3.0 y JSF 2.0. El
web.xml
debe cumplir con la especificación Servlet 3.0 y ya contiene el servlet 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>
El
faces-config.xml
debe cumplir con la especificación 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>
Descargue Tomahawk 1.1.10 para JSF 2.0 . Extraiga el archivo zip, vaya a la carpeta
/lib
y copie todos los archivos*.jar
en su/WEB-INF/lib
.Son 18 archivos, de los cuales
batik*.jar
yxml*.jar
son innecesarios para usar solo el componentet:inputFileUpload
. Podrías dejarlos fuera.Configure el filtro de extensiones Tomahawk en
web.xml
. Es el responsable de gestionarmultipart/form-data
solicitudes demultipart/form-data
que se requieren para poder enviar archivos a través de 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>
Tenga en cuenta que el
<servlet-name>
debe coincidir exactamente con el<servlet-name>
deFacesServlet
comoFacesServlet
enweb.xml
.Crea un Facelet simple,
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>
Tenga en cuenta el
enctype="multipart/form-data"
en<h:form>
, esto es muy importante para poder enviar archivos con HTTP.Crea un bean administrado simple,
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; } }
Eso debería ser. http://localhost:8080/projectname/upload.xhtml por http://localhost:8080/projectname/upload.xhtml .
En cuanto a sus preguntas concretas:
¿Qué debo hacer para pasar el archivo de JSF al bean administrado y luego transformarlo en un byte [] (Para poder manejarlo en el EJB)?
Esto se responde arriba.
¿Cómo puede ayudarme un servlet?
Puede procesar y controlar solicitudes / respuestas HTTP. En un entorno JSF, FacesServlet
ya hace todo el trabajo.
¿Necesito un servlet para hacer esto?
En un entorno JSF, FacesServlet
es obligatorio. Pero ya lo proporciona la API, no necesita escribir uno usted mismo. Sin embargo, para poder descargar archivos desde una base de datos, otro servlet es definitivamente útil. Puede encontrar un ejemplo básico aquí: Servlet para servir contenido estático .
También encontré que en algún blog menciona algo sobre servlets 3.0, pero no sé si mi entorno de trabajo lo está usando, ¿cómo puedo hacerlo si uso servlets 3.0 (estoy usando JEE6)?
Si está utilizando un contenedor Servlet 3.0 como Glassfish 3, JBoss AS 6, Tomcat 7, etc. y el web.xml
está declarado como Servlet 3.0, entonces definitivamente está utilizando Servlet 3.0. Servlet 3.0 es parte de Java EE 6.