Tag: Struts2
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.