简体   繁体   English

Spring MVC文件上传有问题

[英]Having issue with Spring mvc file upload

My spring WebInitializer class adds the dispatcher.setMultipartConfig(new MultipartConfigElement("/")) 我的春季WebInitializer类添加了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. 我的WebMvcConfig类具有带有@Bean批注的multipartResolver()方法。

@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. AppConfig类仅用于导入必要的配置类。

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

}

UploadedFile class UploadedFile类

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 编辑了 uploadXML.jsp 并添加了缺少的encyte属性

2nd Edit added modelAttribute="uploadedFile" 第二次编辑添加了modelAttribute="uploadedFile"

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

<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 最后更新的控制器类添加了@ModelAttribute而不是@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... 编辑我看到我在表单标签上缺少encyte属性...

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 所以...不确定这意味着什么,我的意思是我的控制器方法具有@RequestParam("uploadedFile") UploadedFile文件

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... 并将其更新为@ModelAttribute ,现在允许点击控制器方法...但是, UploadedFile对象的属性为空,这意味着未设置MultipartFile属性。

addition edit added modelAttribute="uploadedFile" to form tag... still looks like custom model UploadedFile property is not binding to MultipartFile 另外,编辑添加了modelAttribute="uploadedFile"到表单标签...仍然看起来像自定义模型UploadedFile属性未绑定到MultipartFile

Any ideas? 有任何想法吗?

Based on the chat discussion. 基于聊天讨论。

The user had two multipart resolvers configured. 用户配置了两个多部分解析器。 One that comes with servlet 3.0 container and another using commons-io. 一个是Servlet 3.0容器随附的,另一个是使用commons-io的。

Removing the dispatcher.setMultipartConfig(new MultipartConfigElement("/")); 删除dispatcher.setMultipartConfig(new MultipartConfigElement("/")); resolved the issue. 解决了问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM