subir mvc imagen form con archivos spring spring-boot apache-commons apache-commons-fileupload

form - subir imagen con spring mvc



SpringBoot: Carga de archivos de transmisiĆ³n grandes usando Apache Commons FileUpload (4)

Gracias a algunos comentarios muy útiles de M.Deinum, logré resolver el problema. He limpiado algunas de mis publicaciones originales y las publico como una respuesta completa para futuras referencias.

El primer error que estaba cometiendo no fue deshabilitar el MultipartResolver predeterminado que proporciona Spring. Esto terminó en el programa de resolución que procesa HttpServeletRequest y, por lo tanto, lo consume 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, había otra trampa oculta esperándome después de esto. Tan pronto como deshabilité la resolución predeterminada de varias partes, 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 requería que enviara mi solicitud POST de la siguiente manera:

<html> <body> <form method="POST" enctype="multipart/form-data" action="/upload?${_csrf.parameterName}=${_csrf.token}"> <input type="file" name="file"><br> <input type="submit" value="Upload"> </form> </body> </html>

También modifiqué un poco mi controlador:

@Controller public class FileUploadController { @RequestMapping(value="/upload", method=RequestMethod.POST) public @ResponseBody Response<String> upload(HttpServletRequest request) { try { boolean isMultipart = ServletFileUpload.isMultipartContent(request); if (!isMultipart) { // Inform user about invalid request Response<String> responseObject = new Response<String>(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<String>(false, "File upload error", e.toString()); } catch (IOException e) { return new Response<String>(false, "Internal server IO error", e.toString()); } return new Response<String>(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érica simple que uso:

public class Response<T> { /** 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 ... }

Estoy tratando de cargar un archivo grande usando la API de carga de archivos de Apache Commons de "transmisión".

La razón por la que estoy usando el Cargador de archivos de Apache Commons y no el cargador de Spring Multipart predeterminado es que falla cuando cargamos archivos de gran tamaño (~ 2 GB). Estoy trabajando en una aplicación GIS donde las cargas de archivos son bastante comunes.

El código completo para mi controlador de carga de archivos es el siguiente:

@Controller public class FileUploadController { @RequestMapping(value="/upload", method=RequestMethod.POST) public void upload(HttpServletRequest request) { boolean isMultipart = ServletFileUpload.isMultipartContent(request); if (!isMultipart) { // Inform user about invalid request return; } //String filename = request.getParameter("name"); // Create a new file upload handler ServletFileUpload upload = new ServletFileUpload(); // Parse the request try { FileItemIterator iter = upload.getItemIterator(request); while (iter.hasNext()) { FileItemStream item = iter.next(); String name = item.getFieldName(); InputStream stream = item.openStream(); if (item.isFormField()) { System.out.println("Form field " + name + " with value " + Streams.asString(stream) + " detected."); } else { System.out.println("File field " + name + " with file name " + item.getName() + " detected."); // Process the input stream OutputStream out = new FileOutputStream("incoming.gz"); IOUtils.copy(stream, out); stream.close(); out.close(); } } }catch (FileUploadException e){ e.printStackTrace(); }catch (IOException e){ e.printStackTrace(); } } @RequestMapping(value = "/uploader", method = RequestMethod.GET) public ModelAndView uploaderPage() { ModelAndView model = new ModelAndView(); model.setViewName("uploader"); return model; } }

El problema es que el getItemIterator(request) siempre devuelve un iterador que no tiene ningún elemento (es decir, iter.hasNext() ) siempre devuelve false .

Mi archivo application.properties es el siguiente:

spring.datasource.driverClassName=org.postgresql.Driver spring.datasource.url=jdbc:postgresql://localhost:19095/authdb spring.datasource.username=georbis spring.datasource.password=asdf123 logging.level.org.springframework.web=DEBUG spring.jpa.hibernate.ddl-auto=update multipart.maxFileSize: 128000MB multipart.maxRequestSize: 128000MB server.port=19091

La vista JSP para el /uploader es la siguiente:

<html> <body> <form method="POST" enctype="multipart/form-data" action="/upload"> File to upload: <input type="file" name="file"><br /> Name: <input type="text" name="name"><br /> <br /> Press here to upload the file!<input type="submit" value="Upload"> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> </form> </body> </html>

¿Qué podría estar haciendo mal?


Intente agregar spring.http.multipart.enabled=false en el archivo application.properties .


Si está utilizando una versión reciente de Spring Boot (estoy usando 2.0.0.M7), 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 la implementación de múltiples implementaciones, la última opción le permite desactivar la implementación Spring predeterminada.


Yo uso kindeditor + springboot. Cuando uso la solicitud (MultipartHttpServletRequest) Podría obtener el archivo, pero uso appeche-common-io: upload.parse (solicitud) el valor de retorno es nulo.

public BaseResult uploadImg(HttpServletRequest request,String type){ MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; MultiValueMap<String, MultipartFile> multiFileMap = multipartRequest.getMultiFileMap();