VERSIONES
- 15/08/2013 (Primera publicación)
- 08/03/2014:
- Actualización del ejemplo a Struts 2.3.16.1 debido a vulnerabilidad en libreria FileUpload
15/08/2013
En el tip anterior vimos el mecanismo de Struts 2 que gestiona la recepción de ficheros enviados con un formulario. Si quisierámos enviar más de un fichero con el mismo formulario, basta con definir para cada fichero los atributos asociados a cada uno y que vimos en ese tip. Es una técnica tosca, pero funciona.
El problema lo tendremos si el número de ficheros es dinámico; esto es, desconocido de antemano. Por fortuna, Struts 2 admite la recepción de múltiples de ficheros de forma sencilla y elegante: recogiéndolos en una lista de objetos File
.
Si retomamos el proyecto del tip anterior, la acción quedaría así:
package com.danielme.tips.struts2.actions; import java.io.File; import java.util.LinkedList; import java.util.List; import com.opensymphony.xwork2.ActionSupport; /** * * @author danielme.com * */ public class SubidaFicheroAction extends ActionSupport { private static final long serialVersionUID = 1L; private List<File> uploadFichero = new LinkedList<File>(); private List<String> uploadFicheroFileName = new LinkedList<String>(); private List<String> uploadFicheroContentType = new LinkedList<String>(); /** ACCIONES **/ public String inicio() { return INPUT; } public String enviar() { if (uploadFichero.isEmpty()) { return INPUT; } else { return SUCCESS; } } /** GETTERS Y SETTERS **/ public List<File> getUploadFichero() { return uploadFichero; } public void setUploadFichero(List<File> uploadFichero) { this.uploadFichero = uploadFichero; } public List<String> getUploadFicheroFileName() { return uploadFicheroFileName; } public void setUploadFicheroFileName(List<String> uploadFicheroFileName) { this.uploadFicheroFileName = uploadFicheroFileName; } public List<String> getUploadFicheroContentType() { return uploadFicheroContentType; } public void setUploadFicheroContentType(List<String> uploadFicheroContentType) { this.uploadFicheroContentType = uploadFicheroContentType; } }
Fíjate bien: el atributo obligatorio uploadFichero
y los opcionales uploadFicheroFileName
y uploadFicheroContentType
se han convertido en listas.
En el formulario definimos o generamos dinámicamente, según sea el caso, un campo para cada fichero con el nombre del atributo de la lista. Por ejemplo:
<s:form action="subirFicheroAction" method="POST" enctype="multipart/form-data"> <s:file name="uploadFichero"/> <s:file name="uploadFichero"/> <s:file name="uploadFichero"/> <s:submit key="send"/> </s:form>
Recuperamos los ficheros subidos recorriendo las listas. Ese es justo el cometido de resultado.jsp, la vista que devuelve la acción: mostrar el contenido de las listas.
uploadFicheroFileName: <ul> <s:iterator value="uploadFicheroFileName"> <li><s:property /></li> </s:iterator> </ul> <br> uploadFicheroContentType <ul> <s:iterator value="uploadFicheroContentType"> <li><s:property /></li> </s:iterator> </ul>
El resultado del proyecto de ejemplo es el siguiente:
El proyecto completo se encuentra en GitHub. Para más información sobre cómo utilizar GitHub, consultar este artículo.
Se puede con input type=file multiple? Mi mentalidad millenial me dice que qué hueva crear un input file para cada archivos que se va a subir.
Sí, puedes hacerlo para navegadores que soporten HTML5. Lo indicas en el s:file con multiple=»multiple».