Struts2 FileUploadInterceptor & Content-Type
by David Sanmartín on Aug.13, 2009, under Struts2, Tecnología, Uncategorized
Tras desarrollar una aplicación para un cliente en Struts2 un día recibimos una incidencia sobre un comportamiento extraño que tenía lugar al subir un fichero. Resulta que el formulario se enviaba sin problemas y se devolvía la correspondiente página indicando que se había modificado correctamente la información. Pero el fichero enviado no se había subido al servidor.
Después de que mi compañero David Canós reprodujera la incidencia en su ordenador me puse a averiguar si había algo en el formulario o en el Action que lo recibe que pudiera ocasionar el error. Activé el log y al probarlo en mi ordenador descubrí que a mi me funcionaba de la forma esperada. No obstante el log predijo que el error se debía a que el servidor no detectaba un Content-Type en el fichero enviado. Cogí el mismo fichero que había probado mi compañero (después de que me lo enviara por mail y también me lo pasara con un pendrive) y me seguía funcionando bien. Entonces pensé que se habría seteado el mime durante la copia de un SO a otro (aunque gastemos el mismo SO) y se lo reenvié para que probara una vez más. Volvió a fallarle. Probó también con otros ficheros y con otros le daba el mismo problema.
Llegados a este punto me puse a pensar y recordé que mi compañero usaba Chrome normalmente y en la empresa donde ocurrió el problema usan Safari (pues principalmente trabajan con Mac) así que no podía ser por un problema del navegador. Pero yo lo había probado con Firefox y con IE7 así que le dije a mi compañero que probara una vez más pero desde Firefox. Cuál fue mi sorpresa cuando el fichero (el mismo de todas las veces) se envió correctamente. Sabiendo el origen y el motivo sólo quedaba arreglar el error. Y ahora es cuando viene lo más divertido: modifiqué la configuración del servidor para que contemplara las extensiones extrañas (app.log.001 por ejemplo) y les asignara por defecto ‘text/plain’ como Mime-Type, pero el problema seguía ocurriendo. Por tanto la solución residía en Struts2 y más concretamente en el FileUploadInterceptor.
Me descargué el código fuente del core de Struts2 para poder acceder al código fuente del FileUploadInterceptor. Después de comprender el proceso del interceptor y de poner un par de System.out para comprobar el momento en el que estaba fallando el código hice la siguiente modificación:
Código antiguo:
...
// Bind allowed Files
Enumeration fileParameterNames = multiWrapper.getFileParameterNames();
while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
// get the value of this input tag
String inputName = (String) fileParameterNames.nextElement();
// get the content type
String[] contentType = multiWrapper.getContentTypes(inputName);
if (isNonEmpty(contentType)) {
// get the name of the file from the input tag
String[] fileName = multiWrapper.getFileNames(inputName);
if (isNonEmpty(fileName)) {
// Get a File object for the uploaded File
...
Código generado:
...
// bind allowed Files
Enumeration fileParameterNames = multiWrapper.getFileParameterNames();
while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
// get the value of this input tag
String inputName = (String) fileParameterNames.nextElement();
// get the content type
String[] contentType = multiWrapper.getContentTypes(inputName);
if((contentType.length < 1) || (contentType[0] == null)){
contentType = new String[]{"text/plain"};
}
if (isNonEmpty(contentType)) {
// get the name of the file from the input tag
String[] fileName = multiWrapper.getFileNames(inputName);
if (isNonEmpty(fileName)) {
// get a File object for the uploaded File
...
De esta forma consigo que si el fichero no trae ningún Content-Type le asigno por defecto el ‘text/plain’ para que no me falle. Por supuesto también me toco modificar la configuración del fichero struts.xml para poder usar mi FileUploadInterceptor modificado en vez del que trae Struts2 en la pila de interceptores ParamsPrepareParamsStack.
La moraleja es que parece que ni Safari ni Chrome le setean el Content-Type de la petición HTTP o uno por defecto al fichero que se envía en un formulario aunque este no tenga Content-Type.
October 2nd, 2009 on 11:23
Hola
Llevo varios días intentando hacer el “ejemplo sencillo” de subir un fichero a un servidor con Struts2 + JSP.
He buscado tanto en español como en ingles (upload file) pero con todos los ejemplos que he probado no he conseguido hacer que funcione ninguno.
¿Me podría facilitar el código para ver porque no me han funcionado los ejemplos que he probado y evr como funcionaría correctamente?
Gracias por adelantado.
Un saludo
October 2nd, 2009 on 11:52
Hola Antonio, el código que empleo yo para la subida de ficheros es el siguiente. En el Action:
private File fichero;
private String ficheroContentType;
private String ficheroFileName;
public File getFichero(){
return fichero;
}
public void setFichero(File fichero){
this.fichero = fichero;
}
public String getFicheroContentType(){
return ficheroContentType;
}
public void setFicheroContentType(String ficheroContentType){
this.ficheroContentType = ficheroContentType;
}
public String getFicheroFileName(){
return ficheroFileName;
}
public void setFicheroFileName(String ficheroFileName){
this.ficheroFileName = ficheroFileName;
}
String ficheroName = null;
if((fichero != null) && (fichero.length() > 0)){
// guardamos el fichero donde queremos
try {
ficheroName = timestamp.format(new Date()) + ficheroFileName;
String fullFileName = rutaFicheros + ficheroName;
File theFile = new File(fullFileName);
FileUtils.copyFile(fichero, theFile);
} catch (Exception e) {
log.error(“Ocurrió un error al tratar el fichero: ” + e.getMessage());
ficheroName = null;
}
}
Y en el jsp:
<s:file name=”fichero” id=”fichero” />
Espero que te sirva. Saludos.
June 1st, 2010 on 13:28
Hola, tengo un problema en mi aplicación, tengo una parte en la que puedo subir una imagen al servidor, selecciona la imagen de mi PC y la sube al ordenador, solo que al mostrar las imagenes subidas al servidor, esta aparece con el típico aspa rojo como si no se encontrara la imagen. Si vuelvo a redesplegar la apliación la imagen aparece correctamente, tiene alguna idea? Uso Struts 2 y servidor de aplicacion Glassfish.
Gracias y un saludo
June 2nd, 2010 on 08:19
Hola Pablo. ¿La imagen que está subiendo al servidor se está almacenando en una ruta relativa a la aplicación? La única opción que se me ocurre en ese caso es que el servidor no la interprete al ser una ruta donde se despliega la aplicación. Si fuera este el caso probaría a cambiar la ruta por otra cualquiera del servidor y usaría el atributo alternatedocroot de Glassfish.
En caso de no ser esto necesitaría más información.
Saludos.
June 14th, 2010 on 12:27
A mi me pasa lo mismo, hasta que no refresco mi proyecto en Eclipse no se entera de las nuevas fotos tomadas de BD como byte[].