Después de consultar expertos en este tema, programadores de varias ramas y maestros dimos con la respuesta al problema y la compartimos en este post.
Solución:
Gracias a algunos comentarios muy útiles de M.Deinum, logré resolver el problema. He limpiado parte de mi publicación original y estoy publicando esto como una respuesta completa para futuras referencias.
El primer error que cometí fue no deshabilitar el valor predeterminado MultipartResolver
que ofrece Spring. Esto terminó en el resolutor procesando el HttpServeletRequest
y así consumirlo antes de que mi controlador pueda actuar sobre él.
La forma de desactivarlo, gracias a M. Deinum fue la siguiente:
multipart.enabled=false
Sin embargo, todavía había otra trampa oculta esperándome después de esto. Tan pronto como deshabilité la resolución multiparte predeterminada, comencé a recibir el siguiente error al intentar realizar una carga:
Fri Sep 25 20:23:47 IST 2015
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'POST' not supported
En mi configuración de seguridad, había habilitado la protección CSRF. Eso requirió que enviara mi solicitud POST de la siguiente manera:
También modifiqué un poco mi controlador:
@Controller
public class FileUploadController
@RequestMapping(value="/upload", method=RequestMethod.POST)
public @ResponseBody Response upload(HttpServletRequest request)
try
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (!isMultipart)
// Inform user about invalid request
Response responseObject = new Response(false, "Not a multipart request.", "");
return responseObject;
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload();
// Parse the request
FileItemIterator iter = upload.getItemIterator(request);
while (iter.hasNext())
FileItemStream item = iter.next();
String name = item.getFieldName();
InputStream stream = item.openStream();
if (!item.isFormField())
String filename = item.getName();
// Process the input stream
OutputStream out = new FileOutputStream(filename);
IOUtils.copy(stream, out);
stream.close();
out.close();
catch (FileUploadException e)
return new Response(false, "File upload error", e.toString());
catch (IOException e)
return new Response(false, "Internal server IO error", e.toString());
return new Response(true, "Success", "");
@RequestMapping(value = "/uploader", method = RequestMethod.GET)
public ModelAndView uploaderPage()
ModelAndView model = new ModelAndView();
model.setViewName("uploader");
return model;
donde Response es solo un tipo de respuesta genérico simple que uso:
public class Response
/** Boolean indicating if request succeeded **/
private boolean status;
/** Message indicating error if any **/
private String message;
/** Additional data that is part of this response **/
private T data;
public Response(boolean status, String message, T data)
this.status = status;
this.message = message;
this.data = data;
// Setters and getters
...
Si está utilizando una versión reciente de Spring Boot (estoy usando 2.0.0.M7), entonces los nombres de las propiedades han cambiado. Spring comenzó a usar nombres específicos de tecnología
spring.servlet.multipart.maxFileSize=-1
spring.servlet.multipart.maxRequestSize=-1
spring.servlet.multipart.enabled=false
Si está obteniendo excepciones de StreamClosed causadas por múltiples implementaciones activas, entonces la última opción le permite deshabilitar la implementación de primavera predeterminada
Aquí tienes las comentarios y puntuaciones
Si guardas algún conflicto y disposición de prosperar nuestro división puedes añadir un exégesis y con placer lo ojearemos.