I'm trying to fix this code, uploading an image file using Struts 2.
When I debug, I verified in my action class, my variables descriptor
, descriptorContentType
, and descriptorFileName
are all coming as null
.
I tried searching for the problem, but have no any results. Here's my code, anyone have idea what´s wrong with this code?
ver.jsp
:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<%@taglib prefix="sj" uri="/struts-jquery-tags"%>
<html>
<head>
<title></title>
<meta name="decorator" content="ajax"/>
</head>
<body>
<s:form action="guardar" id="formularioImagen" enctype="multipart/form-data" method="post">
<s:token name="imagenFichaEmpresaForm"/>
<s:hidden name="codigoFichaEmpresa"/>
<div class="mensajeInfo mensajeRelativo">
<s:text name="fichaEmpresa.texto.imagenInformacion"/>
</div>
<table>
<s:file name="descriptor"/>
</table>
<div style="text-align: center">
<sj:submit name="btnGuardar"
targets="imagenFichaEmpresa"
title="%{getText('comun.textos.guardar')}"
value="%{getText('comun.textos.guardar')}"
formIds="formularioImagen"
/>
<sj:submit name="btnCerrar"
onClickTopics="cerrarUrlImagenes"
title="%{getText('comun.texto.cerrar')}"
value="%{getText('comun.texto.cerrar')}"
/>
</div>
</s:form>
</body>
</html>
struts.xml
:
<package name="clienteFichaEmpresaImagen" namespace="/validador/privado/cliente/fichaEmpresa/imagen" extends="struts-validador">
<action name="listado"
class="com.construdata21.construdata.validador.vista.actions.cliente.FichaEmpresaImagenAction"
method="listado">
<result>/validador/cliente/fichaEmpresa/imagen/listar.jsp</result>
</action>
<action name="eliminarImagen"
class="com.construdata21.construdata.validador.vista.actions.cliente.FichaEmpresaImagenAction"
method="eliminar">
<result type="redirectAction">
<param name="actionName">listado</param>
<param name="codigoFichaEmpresa">${codigoFichaEmpresa}</param>
</result>
</action>
<action name="ver"
class="com.construdata21.construdata.validador.vista.actions.cliente.FichaEmpresaImagenAction"
method="ver">
<result>/validador/cliente/fichaEmpresa/imagen/ver.jsp</result>
</action>
<action name="guardar"
class="com.construdata21.construdata.validador.vista.actions.cliente.FichaEmpresaImagenAction"
method="guardar">
<interceptor-ref name="defaultStack">
<param name="fileUpload.maximumSize">10485760</param> <!-- Max file size: 10MB -->
<param name="fileUpload.allowedTypes">image/jpeg,image/png,image/gif</param> <!-- Allowed types -->
</interceptor-ref>
<result>/validador/cliente/fichaEmpresa/imagen/imagenCorrecta.jsp</result>
<result name="input">/validador/cliente/fichaEmpresa/imagen/ver.jsp</result>
</action>
<action name="moverImagen"
class="com.construdata21.construdata.validador.vista.actions.cliente.FichaEmpresaImagenAction"
method="moverImagen">
<result>/validador/cliente/fichaEmpresa/imagen/listar.jsp</result>
</action>
<action name="validarImagen"
class="com.construdata21.construdata.validador.vista.actions.cliente.FichaEmpresaImagenAction"
method="validarImagen">
<result type="redirectAction">
<param name="actionName">listado</param>
<param name="codigoFichaEmpresa">${codigoFichaEmpresa}</param>
</result>
</action>
</package>
FichaEmpresaImagenAction.java
:
package com.construdata21.construdata.validador.vista.actions.cliente;
import com.construdata21.construdata.cliente.negocio.fachadas.FachadaCliente;
import com.construdata21.construdata.negocio.modelo.Archivo;
import com.construdata21.construdata.negocio.modelo.ArchivoImagen;
import com.construdata21.construdata.negocio.modelo.FichaEmpresa;
import com.construdata21.construdata.negocio.modelo.UsuarioConstrudata;
import com.construdata21.construdata.validador.negocio.fachadas.FachadaValidador;
import com.construdata21.construdata.validador.vista.actions2.ValidadorAction;
import com.construdata21.construdata.vista.comun.FachadaSesion;
import static com.opensymphony.xwork2.Action.SUCCESS;
import com.opensymphony.xwork2.ModelDriven;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Date;
import javax.imageio.ImageIO;
import org.apache.struts2.interceptor.validation.SkipValidation;
public class FichaEmpresaImagenAction
extends ValidadorAction
implements ModelDriven<Archivo> {
public static final int MAX_ANCHO_IMAGEN = 1024;
public static final int MAX_ALTO_IMAGEN = 800;
/**
* Atributo que conten a imaxe
*/
private final ArchivoImagen imagen = new ArchivoImagen();
/**
*
* @return imagen Archivo coa imaxe
*/
@Override
public Archivo getModel() {
return imagen;
}
/**
* Atributo que contén as imaxes da ficha empresa
*/
private Archivo[] imagenes;
/**
* Metodo que retorna o atributo imagenes
*
* @return imagenes Archivo[] coas imaxes
*/
public Archivo[] getImagenes() {
return imagenes;
}
/**
* Atributo co descriptor do arquivo
*/
private File descriptor;
/**
* Método que nos devolve o descriptor do arquivo
*
* @return File co descriptor
*/
public File getDescriptor() {
return descriptor;
}
/**
* Método que establece o descriptor do arquivo
*
* @param descriptor File
*/
public void setDescriptor(File descriptor) {
this.descriptor = descriptor;
}
private String descriptorContentType;
/**
* Content type do arquivo
*
* @return String descriptorContentType
*/
public String getDescriptorContentType() {
return descriptorContentType;
}
/**
* Método que establece o content type
*
* @param descriptorContentType
*/
public void setDescriptorContentType(String descriptorContentType) {
this.descriptorContentType = descriptorContentType;
}
/**
* Atributo co nome do descriptor
*/
private String descriptorFileName;
/**
* Método que nos devolve o nome do arquivo
*
* @return String
*/
public String getDescriptorFileName() {
return descriptorFileName;
}
/**
* Método que nos establece o nome do arquivo
*
* @param descriptorFileName
*/
public void setDescriptorFileName(String descriptorFileName) {
this.descriptorFileName = descriptorFileName;
}
/**
* Atributo que representa o codigo da ficha empresa
*/
private int codigoFichaEmpresa;
/**
* Metodo que retorna o codigo da ficha empresa
*
* @return codigoFichaEmpresa int co codigo
*/
public int getCodigoFichaEmpresa() {
return codigoFichaEmpresa;
}
/**
* Metodo que establece o codigo da ficha empresa
*
* @param codigoFichaEmpresa int co codigo
*/
public void setCodigoFichaEmpresa(int codigoFichaEmpresa) {
this.codigoFichaEmpresa = codigoFichaEmpresa;
}
/**
* Método encargado de visualizar unha imaxe da ficha empresa
*
* @return String co resultado da execución do action
* @throws Exception
*/
@SkipValidation
public String ver() throws Exception {
return SUCCESS;
}
/**
* Método encargado de gardar unha imaxe da ficha empresa
*
* @return String co resultado da execución do action
* @throws Exception
*/
public String guardar() throws Exception {
UsuarioConstrudata usuario = (UsuarioConstrudata) this.getSession().get(FachadaSesion.USUARIO_SESION_VALIDADOR);
if (codigoFichaEmpresa > 0) {
imagen.setArchivo(Files.readAllBytes(descriptor.toPath()));
imagen.setLongitud(descriptor.getTotalSpace());
imagen.setNombre(descriptorFileName);
imagen.setFechaValidacion(new Date());
imagen.setCodigo(FachadaValidador.guardarImagenFichaEmpresa(codigoFichaEmpresa, imagen, usuario));
FachadaValidador.validarArchivoImagen(
imagen.getCodigo(),
usuario.getCodigo());
}
return SUCCESS;
}
/**
* Metodo que executa a accion de eliminar as imaxes
*
* @return String co resultado
* @throws java.lang.Exception
*/
@SkipValidation
public String eliminar() throws Exception {
UsuarioConstrudata usuario = (UsuarioConstrudata) this.getSession().get(FachadaSesion.USUARIO_SESION_VALIDADOR);
if (codigoFichaEmpresa > 0 && imagen.getCodigo() > 0) {
FachadaValidador.fichaEmpresaImagenEliminar(codigoFichaEmpresa,
imagen.getCodigo(),
usuario);
}
return SUCCESS;
}
/**
* Metodo que executa a accion de listar
*
* @return String co resultado
* @throws java.lang.Exception
*/
@SkipValidation
public String listado() throws Exception {
UsuarioConstrudata usuarioSesion = (UsuarioConstrudata) getSession().get(FachadaSesion.USUARIO_SESION_VALIDADOR);
FichaEmpresa fichaEmpresa = FachadaCliente.getFichaEmpresaCompleta(codigoFichaEmpresa, usuarioSesion);
imagenes = fichaEmpresa.getImagenes();
return SUCCESS;
}
/**
* Metodo que executa a accion de listar
*
* @return String co resultado
* @throws java.lang.Exception
*/
@SkipValidation
public String moverImagen() throws Exception {
if (imagen.getCodigo() > 0 && codigoFichaEmpresa > 0) {
FachadaCliente.modificarOrdenImagenFichaEmpresa(
codigoFichaEmpresa,
imagen.getCodigo(),
imagen.getOrden()
);
}
UsuarioConstrudata usuarioSesion = (UsuarioConstrudata) getSession().get(FachadaSesion.USUARIO_SESION_VALIDADOR);
FichaEmpresa fichaEmpresa = FachadaCliente.getFichaEmpresaCompleta(codigoFichaEmpresa, usuarioSesion);
imagenes = fichaEmpresa.getImagenes();
return SUCCESS;
}
/**
* Metodo que valida unha imaxe
*
* @return resultado String co resultado
* @throws Exception
*/
@SkipValidation
public String validarImagen() throws Exception {
if (imagen.getCodigo() > 0) {
UsuarioConstrudata usuario = (UsuarioConstrudata) this.getSession().get(FachadaSesion.USUARIO_SESION_VALIDADOR);
FachadaValidador.validarArchivoImagen(imagen.getCodigo(), usuario.getCodigo());
}
return SUCCESS;
}
/**
* Metodo que valida o formulario (Imaxe)
*/
@Override
public void validate() {
super.validate();
BufferedImage img = null;
if (descriptor != null) {
try {
img = ImageIO.read(descriptor);
} catch (IOException ex) {
}
if (img != null) {
if (img.getWidth() > MAX_ANCHO_IMAGEN) {
this.addFieldError("descriptor", "Ha superado el ancho permitido: " + MAX_ANCHO_IMAGEN);
} else if (img.getHeight() > MAX_ALTO_IMAGEN) {
this.addFieldError("descriptor", "Ha superado el alto permitido: " + MAX_ALTO_IMAGEN);
}
} else {
this.addFieldError("descriptor", "El archivo no es una imagen");
}
} else {
this.addFieldError("descriptor", "Selecciona un archivo");
}
}
}
First, you should check your action configuration. The package, which contains a file uploading action config inerits struts-validator
. Whatever this package is define is unknown (there'no source code available). But it should extent struts-default
. This is a default configuration where defaultStack
of interceptors is defined. See docs.
Since, you use it in your action config you should be aware of fileUpload
interceptor is reaching, after it is chained by the interceptor stack defaultStack
. This stack is big and used for getting a common functionality of Struts action, until it has been overriden by the action config. You did it to change some properties of fileUpload
interceptor, but didn't change the defaultStack
and probably the order of interceptors in the stack. Especially, you need it to create a custom stack, since your action class implements a ModelDriven
.
I would not recommend you to use ModelDriven
, because you might have problems with implementing it correctly. For example, you have a wrong type returned by getModel()
. The modelDriven
interceptor pushes the model object to the value stack, this is where fileUpload
interceptor is expecting to find setters to store the properties of the uploaded file, such as
descriptor
, descriptorContentType
, and descriptorFileName
. But in your case you defined them in the action class.
You are also submitting other textfield values along with the file descriptor
using multipart/form-data
form encoding. Therefore, you should provide appropriate setters to the object where the file properties are stored.
The fileUpload
interceptor is deprecated in the current version of Struts, and replaced with actionFileUpload
. You can find more if you read this answer.