Tip Struts 2 #01: subida de ficheros


VERSIONES

  1. 12/08/2013 (Primera publicación)
  2. 08/03/2014:
    • Actualización del ejemplo a Struts 2.3.16.1 debido a vulnerabilidad en libreria FileUpload
  3. 14/09/2014:
    • Comentario sobre validación automática y FieldError

12/08/2013
struts2 tip

Struts 2 proporciona de serie soporte para la subida de ficheros desde un formulario. Para ello, en primer lugar definiremos en nuestro Action como mínimo un atributo de tipo java.io.File con el nombre que queramos. Usando ese mismo nombre, si lo deseamos también podemos agregar dos atributos adicionales que serán gestionados de forma automática por Struts y que tendrán el mismo nombre pero con los sufijos ContentType y FileName que contendrán el MimeType y el nombre del fichero respectivamente.

package com.danielme.tips.struts2.actions;

import java.io.File;

import com.opensymphony.xwork2.ActionSupport;

/**
 * 
 * @author danielme.com
 *
 */
public class SubidaFicheroAction extends ActionSupport 
{	

	private static final long serialVersionUID = 1L;
	
	private File uploadFichero;
	private String uploadFicheroFileName;
	private String uploadFicheroContentType;	
	
	/** ACCIONES **/
	
	public String inicio() 
	{
        return INPUT;
    }
	
	public String enviar()
	{
		if (uploadFichero == null)
		{
			return INPUT;
		}
		else
		{
			return SUCCESS;
		}
	}

	/** GETTERS Y SETTERS **/
    public File getUploadFichero()
	{
		return uploadFichero;
	}

	public void setUploadFichero(File uploadFichero)
	{
		this.uploadFichero = uploadFichero;
	}

	public String getUploadFicheroFileName()
	{
		return uploadFicheroFileName;
	}

	public void setUploadFicheroFileName(String uploadFicheroFileName)
	{
		this.uploadFicheroFileName = uploadFicheroFileName;
	}

	public String getUploadFicheroContentType()
	{
		return uploadFicheroContentType;
	}

	public void setUploadFicheroContentType(String uploadFicheroContentType)
	{
		this.uploadFicheroContentType = uploadFicheroContentType;
	}

}	

En nuestro formulario vamos a crear el campo para la subida del fichero con la etiqueta s:file indicando al menos el nombre del atributo de tipo File de nuestro Action. Asimismo, y esto ya es un concepto de html básico, nuestro formulario debe permitir la subida de ficheros por lo que nos aseguramos de definirlo con los atributos method=”POST” enctype=”multipart/form-data”

<s:form action="subirFicheroAction" method="POST" enctype="multipart/form-data">
	
			<s:text name='label'/>:<s:file name="uploadFichero" accept="application/pdf"/>
			
			<s:submit key="send"/>
		</s:form>

Se puede indicar al navegador, mediante el atributo accept de html y admitido por s:file, los MIME type de los ficheros seleccionables. Esto no exime de realizar la validación en el servidor puesto que es posible que el navegador no soporte este atributo y aunque lo soporte, el cuadro de diálogo de selección de archivo suele permitir elegir cualquier fichero tal y como muestra la siguiente captura tomada de Google Chrome en Windows 7.

file chooser

Por último, debemos configurar el interceptor FileUpload, responsable de gestionar la subida de ficheros. Este interceptor forma parte de la pila de interceptores por defecto de Struts 2 por lo que lo más probable es lo que tengamos ya operativo y no tendremos que hacer nada. No obstante conviene echarle un vistazo a su configuración (opcional) que permite definir los tipos de ficheros, extensiones y tamaño máximo permitido en bytes (propiedades que también podemos validar programáticamente en nuestro Action). Con respecto al tamaño, hay que tener en cuenta que este ya está limitado por el contenedor/servidor de aplicaciones. El struts.xml del proyecto de ejemplo es el siguiente:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>

	<constant name="struts.devMode" value="true" />
	<constant name="struts.custom.i18n.resources" value="global" />


	<package name="default" namespace="/" extends="struts-default">

		<action name="inicio" class="com.danielme.tips.struts2.actions.SubidaFicheroAction" method="inicio">
			<result name="input">/jsp/formulario.jsp</result>
		</action>

		<action name="subirFicheroAction" class="com.danielme.tips.struts2.actions.SubidaFicheroAction" method="enviar">
			
			<interceptor-ref name="fileUpload">
				<param name="allowedTypes">application/pdf</param>
                <param name="maximumSize">2000000</param>
				<param name="allowedExtensions">pdf</param>
			</interceptor-ref>
			<interceptor-ref name="defaultStack" />
			
			<result name="input">/jsp/formulario.jsp</result>
			<result name="success">/jsp/resultado.jsp</result>
			
		</action>


	</package>

</struts>
	

Como valor global para todas las acciones que impliquen subida de documentos, se puede definir un límite común de tamaño máximo de fichero admitido con la siguiente constante:

   <constant name="struts.multipart.maxSize" value="1000000" />

Con esto ya lo tenemos todo listo, pero conviene internacionalizar los mensajes de error por defecto del interceptor. En el proyecto de ejemplo se utiliza el fichero global_es.properties para los mensajes en español:

struts.messages.error.file.too.large=El fichero es demasiado grande
struts.messages.error.content.type.not.allowed=Tipo no permitido
struts.messages.error.file.extension.not.allowed = Extensión no permitida
title=tip 1 - subida de fichero
label=Seleccione un fichero pdf
send=Enviar

En el caso de que se produzca uno de estos errores, el mensaje de error se guardará como un FieldError y, si no hemos implementado una validación personalizada siguiendo los mecanismos de Struts, automáticamente se ejecutará el result INPUT del action hacia el que hacemos el submit. Los mensajes de tipo FieldError se muestran automáticamente junto al campo si usamos para renderizar una plantilla o theme de Struts 2 que así lo haga (la plantilla por defecto ya lo hace así). En caso contrario, podemos imprimir el error con la etiqueta s:fielderror. Para más información al respecto, consultar el tip 16.

Si ejecutamos el proyecto de ejemplo, veremos el siguiente formulario:

tip1-1

Si subimos un fichero que cumpla con los requisitos el resultado será el siguiente:

tip1-2

El proyecto completo para Maven se encuentra en Github. Para más información sobre cómo utilizar GitHub, consultar este artículo.

<< TIPS STRUTS 2

2 Responses to Tip Struts 2 #01: subida de ficheros

  1. ruben dice:

    y donde se ubica el fichero subido?

    • danielme.com dice:

      El fichero lo tienes accesible en el atributo uploadFichero para poder hacer lo que necesites con él. Físicamente se encuentra en un directorio temporal del servidor.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: