Uso de un componente JSF de subida de ficheros al servidor con el soporte de Primefaces.
0. Índice de contenidos.
- 1. Introducción.
- 2. Entorno.
- 3. Configuración.
- 4. Subida única de ficheros.
- 5. Subida múltiple de ficheros.
- 6. Soporte de Drag & Drop.
- 7. Referencias.
- 8. Conclusiones.
1. Introducción
En este tutorial vamos a ver cómo hacer uso del componente de subida de ficheros al servidor de Primefaces en su última versión, la 3.0.1.
En esta última versión, la gente de Primefaces ha reescrito muchos de los componentes visuales de la librería, entre estos se encuentra el de subida de ficheros, que ahora usa el soporte de html5 y ya no hace uso de flash. Esta reescritura de componentes en su versión 3 es lo que ha hecho que la librería no guarde una compatibilidad hacía atrás con las versiones anteriores y hace que los componentes que ahora se basan en html5 funcionen correctamente con todas sus propiedades únicamente en navegadores que soporten totalmente html5.
Si pensamos en hacer uso del componente de subida de ficheros en navegadores como IE en sus versiones anteriores a la 9, tendremos que conocer esta limitación; solo funcionará en modo subida única de ficheros.
El objetivo del tutorial es ver cómo incluir el soporte para la subida de ficheros en nuestra aplicación, que ya está configurada para usar la librería de Primefaces, y cómo hacer uso del componente visual en todas sus modalidades
2. Entorno.
El tutorial está escrito usando el siguiente entorno:
- Hardware: Portátil MacBook Pro 15′ (2.4 GHz Intel Core i7, 8GB DDR3 SDRAM).
- Sistema Operativo: Mac OS X Lion 10.7.2
- JSF 2.1, Mojarra 2.1.4
- Primefaces 3.0.1
- Apache Tomcat 7.0.6
3. Configuración.
Lo primero que necesitamos es configurar el siguiente filtro en el fichero de descriptor de despligue web.xml:
<filter> <filter-name>PrimeFaces FileUpload Filter</filter-name> <filter-class> org.primefaces.webapp.filter.FileUploadFilter </filter-class> <init-param> <param-name>thresholdSize</param-name> <param-value>51200</param-value> </init-param> <init-param> <param-name>uploadDirectory</param-name> <param-value>/Users/local/temp</param-value> </init-param> </filter> <filter-mapping> <filter-name>PrimeFaces FileUpload Filter</filter-name> <servlet-name>Faces Servlet</servlet-name> </filter-mapping>
El filtro hace referencia al nombre que hayamos proporcionado al servlet de JSF y la configuración es idéntica en la versión 2.2.1 de Primefaces, pudiendo asignar dos parámetros de inicialización:
- thresholdSize: límite máximo de tamaño de los ficheros para mantenerlos en memoria, si un fichero excede de dicho parámetro, expresado en bytes, se escribirá como un fichero temporal en el directorio especificado en el siguiente parámetro,
- uploadDirectory: directorio en el que se escriben los ficheros temporales que exceden del límite indicado en bytes en el parámetro anterior.
Lo siguiente es añadir las siguientes librerías dentro de nuestro proyecto, haciendo uso de maven bastaría con incluir las siguientes dependencias en nuestro pom.xml:
<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>1.4</version> </dependency>
4. Subida única de ficheros.
Una vez tenemos la configuración antes dicha, ya podemos hacer uso del componente de subida de ficheros, previa declaración del espacio de nombres de Primefaces en el nodo raíz de nuestro árbol de componentes visuales.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui"> <ui:composition template="/WEB-INF/templates/defaultLayout.xhtml"> <ui:define name="title">#{msg['menu.sandbox.fileUpload']}</ui:define> <ui:define name="content"> <h:form id="basicUpload"> <p:messages showDetail="true"/> <p:fileUpload value="#{fileUploadBean.file}" mode="simple"/> <br /><br /> <p:commandButton value="Submit" ajax="false" actionListener="#{fileUploadBean.upload}"/> </h:form> </ui:define> </ui:composition> </html>
La página está montada con el soporte de plantillas de facelets.
El componente <p:fileUpload> estará mapeado contra una propiedad en un managedBean que ahora veremos y en la lógica de control del componente de acción ya dispondremos del fichero poblado en dicha propiedad, para acceder a su contenido y cualquiera de sus propiedades.
import java.io.Serializable; import javax.faces.application.FacesMessage; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; import javax.faces.context.FacesContext; import org.primefaces.model.UploadedFile; @ManagedBean @ViewScoped public class FileUploadBean implements Serializable{ private static final long serialVersionUID = 4352236420460919694L; private UploadedFile file; public UploadedFile getFile() { return file; } public void setFile(UploadedFile file) { this.file = file; } public void upload() { FacesMessage msg = new FacesMessage("Ok", "Fichero " + file.getFileName() + " subido correctamente."); FacesContext.getCurrentInstance().addMessage(null, msg); } }
Con todo ello, tendremos una interfaz como la que sigue:
5. Subida múltiple de ficheros.
Podemos también hacer uso del componente en su modalidad de subida múltiple de ficheros, para lo cual basta con modificar el componente con las siguientes propiedades:
... <p:fileUpload fileUploadListener="#{fileUploadBean.handleFileUpload}" mode="advanced" update="messages" multiple="true" sizeLimit="5000000" allowTypes="/(\.|\/)(gif|jpe?g|png)$/" /> ...
Vemos que, en vez de mapear una propiedad de un bean, programamos la ejecución de un evento de escucha que recibirá encapsulado el fichero en un método en el controlador. Así mismo, también podemos limitar el tamaño de los ficheros a subir (expresado en bytes) y el formato de los mismos en base a las extensiones de ficheros.
En el controlador deberíamos tener un método de escucha como el siguiente que será invocado al pulsar sobre los botones de upload.
... public void handleFileUpload(FileUploadEvent event) { FacesMessage msg = new FacesMessage("Ok", "Fichero " + event.getFile().getFileName() + " subido correctamente."); FacesContext.getCurrentInstance().addMessage(null, msg); } ...
El resultado será un componente visual como el siguiente:
Se puede internacionalizar con literales personalizados haciendo uso de los atributos: cancelLabel y uploadLabel. También se puede programar con autoUpload de modo que los ficheros se van subiendo al servidor a medida que se seleccionan.
Existe una limitación en la versión actual por la cuál no podemos incluir más de un componente en modalidad de subida múltiple de ficheros en un mismo formulario.
6. Soporte de Drag & Drop.
Una de las nuevas características del componente de subida de ficheros en html5 es el soporte de drag & drop que permite arrastrar directamente un fichero desde el sistema de archivos del sistema operativo del cliente al componente en el navegador para añadirlo a la selección de ficheros a subir o subirlo directamente. El componente de Primefaces también le da soporte y está activado por defecto, en caso de necesitar deshabilitarlo podemos hacer uso de la propiedad dragDropSupport que por defecto en true.
7. Referencias.
- http://www.primefaces.org/showcase-labs/ui/fileUploadHome.jsf
8. Conclusiones.
Como contamos en nuestros cursos de JSF, sus componentes nos encapsulan el lenguaje de cliente y nos abstraen de trabajar con el html y/o javascript necesarios para realizar este tipo de funcionalidades más o menos manualmente pero, sobre todo, nos facilitan las tareas de mapeo, conversión y validación de los valores que encapsulan en la lógica de control de nuestra aplicación.
Primefaces, como librería de componentes visuales para JSF, nos proporciona una serie de componentes, listos para usar, de una gran calidad.
Un saludo.
Jose
Hola José, muchas gracias por el tutorial, tengo una inquietud al guardar en la base de datos, no comprendo donde está la ruta de entrada y la ruta donde se guardan las imágenes… agradeciera mucho esta ayuda.
Como puedo cambiar el texto de los botones Choose, Upload y Cancel?
HJEV si podes cambiarlos en el p:fileUpload estan estos atributos.
cancelLabel=»Cancelar» uploadLabel=»Subir» label=»Elegir» , con eso modificas los textos.
Por cierto a Alguien le funciono ? Yo estoy usando windows y no me sube el archivo a la carpeta especificada.
No se si alguien me puede ayudar.
Pero esto no sube los archivos a base de datos. Falta la parte más importante
Hola
Esto me permite guardar uno a uno los ficheros pero como puedo hacer que estos se almacenen las veces que se requieran y al final cree el fichero para subirlo a la bd.
Saludos.
Hola José, oye al usarlo el fileUpload me genera un archivo temporal cuando el archivo sobrepasa los 51200 (Bytes) definidos en el filtro, es decir subo archivos mas pesados como de 77000 (bytes) y me genera archivos.tmp, ¿como puedo eliminar éstos después de subirlos?
PD: Aclaro que ya amplié el 51200 a 100000, pero me seguirá pasando lo mismo si subo archivos que pesen más de 1Mb y no tengo espacio para alojar los .tmp.
Gracias!
hola un favor como hago para definir una ruta especifica en mi proyecto. o donde queda almacenado??
hola jose muchas gracias por el tuto una consulta como puedo hacer una previsualización del archivo que estoy cargando antes de enviarlo al servidor