mardi 31 mars 2015

Having issue with Spring mvc file upload

My spring WebInitializer class adds the dispatcher.setMultipartConfig(new MultipartConfigElement("/"))



public class WebInitializer implements WebApplicationInitializer {

private static final String DISPATCHER_SERVLET_NAME = "dispatcher";
private static final String DISPATCHER_SERVLET_MAPPING = "/";
private static final Logger log = Logger.getLogger(WebInitializer.class);

@Override
public void onStartup(ServletContext servletContext) throws ServletException {

AnnotationConfigWebApplicationContext ctx
= new AnnotationConfigWebApplicationContext();
ctx.register(AppConfig.class);
log.debug(ctx);
// Add the servlet mapping manually and make it initialize automatically
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(DISPATCHER_SERVLET_NAME, new DispatcherServlet(ctx));

dispatcher.addMapping(DISPATCHER_SERVLET_MAPPING);
dispatcher.setLoadOnStartup(1);
dispatcher.setMultipartConfig(new MultipartConfigElement("/"));

EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);

CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);

FilterRegistration.Dynamic characterEncoding = servletContext.addFilter("characterEncoding", characterEncodingFilter);
characterEncoding.addMappingForUrlPatterns(dispatcherTypes, true, "/*");

FilterRegistration.Dynamic security = servletContext.addFilter("springSecurityFilterChain", new DelegatingFilterProxy());
security.addMappingForUrlPatterns(dispatcherTypes, true, "/*");
log.debug(security);

FilterRegistration.Dynamic sitemesh = servletContext.addFilter("sitemesh", new MySiteMeshFilter());
sitemesh.addMappingForUrlPatterns(dispatcherTypes, true, "*.jsp");

servletContext.addListener(new ContextLoaderListener(ctx));
}
}


My WebMvcConfig class has a multipartResolver() method with @Bean annotation.



@EnableWebMvc
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

private static final Logger log = Logger.getLogger(WebMvcConfig.class);

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
log.debug(configurer);
}

@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/pages/");
viewResolver.setSuffix(".jsp");
log.debug(viewResolver);
return viewResolver;
}

@Bean
public SimpleMappingExceptionResolver exceptionResolver() {
SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();

Properties exceptionMappings = new Properties();

exceptionMappings.put("java.lang.Exception", "error/error");
exceptionMappings.put("java.lang.RuntimeException", "error/error");

exceptionResolver.setExceptionMappings(exceptionMappings);

Properties statusCodes = new Properties();

statusCodes.put("error/404", "404");
statusCodes.put("error/error", "500");

exceptionResolver.setStatusCodes(statusCodes);

log.debug(exceptionResolver);
return exceptionResolver;
}

@Bean
public CommonsMultipartResolver multipartResolver(){
CommonsMultipartResolver cmr = new CommonsMultipartResolver();
cmr.setDefaultEncoding("UTF-8");
cmr.setMaxUploadSize(-1);
return cmr;
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
log.debug(registry);
}
}


The AppConfig class is used to just for importing necessary configuartion classes.



@Configuration
@ComponentScan(basePackages = {"edu.indstate.ics.transcript"})
@Import(value = {WebMvcConfig.class, SecurityConfig.class, DataConfig.class})
public class AppConfig {

}


UploadedFile class



public class UploadedFile {

private MultipartFile uploadedFile;
private String name = null;

public MultipartFile getUploadedFile() {
return uploadedFile;
}

public void setUploadedFile(MultipartFile uploadedFile) {
this.uploadedFile = uploadedFile;
this.name = uploadedFile.getOriginalFilename();
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}


Edited uploadXML.jsp and added missing encyte attribute


2nd Edit added modelAttribute="uploadedFile"



<%@ taglib prefix="form" uri="http://ift.tt/IED0jK"%>

<div class="modal fade" id="uploadXMLTranscript" tabindex="-1" role="dialog" aria-hidden="true">
<form:form id="uploadXMLTranscriptForm" method="POST" modelAttribute="uploadedFile" enctype='multipart/form-data' action="uploadXMLTranscript?${_csrf.parameterName}=${_csrf.token}">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times; </span></button>
<h4 class="modal-title">Upload XML Transcript</h4>
</div>
<div class="modal-body">
<p>
<div class="input-group">
<label for="file">Transcript Id: </label>
<input id="file" type="file" name="uploadedFile" accept="text/xml" />
</div>
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="submit" class="btn btn-primary" >Upload</input>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</form:form>
</div><!-- /.modal -->


and finally the controller class updated added @ModelAttribute instead of @RequestParam



@Controller
public class TranscriptUploadController {

private static final Logger logger = Logger.getLogger(TranscriptUploadController.class);

@Autowired
private TranscriptBo transcriptBo;

@RequestMapping(value = {"/", "/secure/uploadXMLTranscript**"}, method = RequestMethod.POST)
public String uploadXMLTranscript(@ModelAttribute("uploadedFile") UploadedFile file, ModelMap model) {
String userName = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

TranscriptStatusCounts transStatCount = transcriptBo.findTranscriptStatusCount();

logger.debug(file);

model.addAttribute("uploadedFile", new UploadedFile());
model.addAttribute("transStatCount", transStatCount);
model.addAttribute("userName", userName);

logger.debug("Preparing to transform uploadedFile object = " + file);

List<Swbhxml> transcripts = new ArrayList<>();
// transcripts.add(transcript);

model.addAttribute("transcripts", transcripts);
model.addAttribute("headerTitle", "Search by Transcript Last Name Results");

if (null != transcripts && transcripts.size() > 0) {
model.addAttribute("transcript", transcripts.get(0));
} else {
model.addAttribute("transcript", new Swbhxml());
}

return "secure/transcript/viewStudentTranscript";
}
}


I have been messing with this for a while and appreciate any assistance.


Thanks!


EDITED I saw I was missing encyte attribute on the form tag...


But now the error has changed to:



org.springframework.web.bind.MissingServletRequestParameterException: Required UploadedFile parameter 'uploadedFile' is not present


So...not sure what this means, I mean my controller method has the @RequestParam("uploadedFile") UploadedFile file


AND updated that to @ModelAttribute which now allows controller method to be hit...however, the UploadedFile object properties are null meaning that MultipartFile property is not being set...


addition edit added modelAttribute="uploadedFile" to form tag... still looks like custom model UploadedFile property is not binding to MultipartFile


Any ideas?


Aucun commentaire:

Enregistrer un commentaire