mvc - upload file from jsp to spring controller
Spring Security & Multipart requests (4)
El problema es que estoy usando un PUT en lugar de un POST. Commons FileUpload está codificado para solo aceptar solicitudes de archivos POST.
Compruebe el método isMultipartContent allí. Para solucionar esto, use un POST o amplíe esa clase y anule ese método para que funcione como prefiera.
Abrí FILEUPLOAD-214 para este problema.
Tengo un @Controller protegido con Spring Security y OAuth2 en el que trato de dejar que mis usuarios carguen un archivo:
@Controller
@RequestMapping(value = "/api/image")
public class ImageController {
@PreAuthorize("hasAuthority(''ROLE_USER'')")
@RequestMapping(value = "/upload", method = RequestMethod.PUT)
public @ResponseBody Account putImage(@RequestParam("title") String title, MultipartHttpServletRequest request, Principal principal){
// Some type of file processing...
System.out.println("-------------------------------------------");
System.out.println("Test upload: " + title);
System.out.println("Test upload: " + request.getFile("file").getOriginalFilename());
System.out.println("-------------------------------------------");
return ((Account) ((OAuth2Authentication) principal).getPrincipal());
}
}
Cuando intento subir un archivo y un título, aparece la siguiente excepción. Estoy configurando el encabezado Content-Type en multipart / form-data.
java.lang.IllegalStateException: Current request is not of type [org.springframework.web.multipart.MultipartHttpServletRequest]: SecurityContextHolderAwareRequestWrapper[ FirewalledRequest[ org.apache.catalina.connector.RequestFacade@1aee75b7]]
at org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver.resolveArgument(ServletRequestMethodArgumentResolver.java:84)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:75)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:156)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:117)
¿Cómo puedo hacer cargas de archivos detrás de Spring Security? Parece que la solicitud nunca se convierte en una MultiPartHttpServerRequest y, por lo tanto, no funciona.
Si cambio la firma de mi método para tomar un @RequestParam MultipartFile, entonces recibo una excepción como:
DEBUG DefaultListableBeanFactory - Returning cached instance of singleton bean ''imageController''
DEBUG ExceptionHandlerExceptionResolver - Resolving exception from handler [public com.tinsel.server.model.Account com.tinsel.server.controller.ImageController.putImage(java.lang.String,org.springframework.web.multipart.MultipartFile,java.security.Principal)]: java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?
DEBUG ResponseStatusExceptionResolver - Resolving exception from handler [public com.tinsel.server.model.Account com.tinsel.server.controller.ImageController.putImage(java.lang.String,org.springframework.web.multipart.MultipartFile,java.security.Principal)]: java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?
DEBUG DefaultHandlerExceptionResolver - Resolving exception from handler [public com.tinsel.server.model.Account com.tinsel.server.controller.ImageController.putImage(java.lang.String,org.springframework.web.multipart.MultipartFile,java.security.Principal)]: java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?
DEBUG DispatcherServlet - Could not complete request
java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?
at org.springframework.util.Assert.notNull(Assert.java:112)
... pero tengo un MultipartResolver configurado en mi XML:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="268435456"/> <!-- 256 megs -->
</bean>
Vi esta publicación en el blog sobre cómo funciona esto en Spring 3.0 , pero estoy intentando estar más actualizado y estoy usando 3.1 actualmente. ¿Hay quizás una solución actualizada?
En Config.groovy
Asegúrese de que multiparte esté habilitado,
// whether to disable processing of multi part requests
grails.web.disable.multipart=false
En el controlador, agregue el método de publicación
def upload(){
MultipartHttpServletRequest mpr = (MultipartHttpServletRequest)request;
if(request instanceof MultipartHttpServletRequest)
{
CommonsMultipartFile f = (CommonsMultipartFile) mpr.getFile("myFile");
println f.contentType
f.transferTo()
if(!f.empty)
flash.message = ''success''
else
flash.message = ''file cannot be empty''
}
else
flash.message = ''request is not of type MultipartHttpServletRequest''}
con estos, pude subir el archivo, nada relacionado con Spring Security.
Para resolver el problema, no use Spring MultiPartHttpServerRequest, sino que tome la solicitud como HttpServletRequest, utilizando la biblioteca de carga de archivos commons de apache para analizar la solicitud desde el método PUT y procesar el archivo. Aquí hay algunos ejemplos de código:
ServletFileUpload fileUpload = new ServletFileUpload(new DiskFileItemFactory());
List<FileItem> fileItems = fileUpload.parseRequest(httpServletRequest);
InputStream in = fileItems.get(0).getInputStream();
...
puede echarle un vistazo a https://github.com/joshlong/the-spring-tutorial que tiene un ejemplo que demuestra cómo publicar en Spring MVC con Spring Security OAuth habilitado. Incluso uso arrastrar y soltar HTML5 para arrastrar la imagen a la pantalla y luego enviarla a ajax al servidor.