zoukankan      html  css  js  c++  java
  • spring-mvc文件下载出现异常:java.lang.IllegalStateException: getOutputStream() has already been called for this response

    最近做文件下载的功能,大概就是下载一个excel模板,前端提交表单时,请求后台下载的controller
     
    发现后台逻辑结束后,后台出现异常,虽然没有影响文件下载的功能,但考虑到异常有影响程序的运行的风险,所以想办法去除这个异常。
     
    异常如下:
     
    java.lang.IllegalStateException: getOutputStream() has already been called for this response
        at org.apache.catalina.connector.Response.getWriter(Response.java:564)
        at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:212)
        at org.springframework.web.servlet.view.freemarker.FreeMarkerView.processTemplate(FreeMarkerView.java:366)
        at org.springframework.web.servlet.view.freemarker.FreeMarkerView.doRender(FreeMarkerView.java:283)
        at org.springframework.web.servlet.view.freemarker.FreeMarkerView.renderMergedTemplateModel(FreeMarkerView.java:233)
        at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:167)
        at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:250)
        at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1047)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:817)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
        at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
        at com.airport.common.web.ProcessTimeFilter.doFilter(ProcessTimeFilter.java:35)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:94)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:502)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1156)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1539)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1495)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:745)

    controller:

        @RequestMapping("/certificate_import/v_download_template.do")
         public String downloadTemplate(HttpServletRequest request,  HttpServletResponse response) {
               log.info("下载证书导入模板...");
               File template =  cmsCertificateImportMng.getCertificateDataTemplate();
               if (template == null) {
                    log.warn("没有获取到证书数据导入模板文件,下载失败");
                    return "certificate_import/list";
               }
               // 将文件流写入response
               FileDownloadUtils.writeFile2Response(response,  template);
               return "certificate_import/import";
         }

    其中FileDownloadUtils.writeFile2Response方法将文件流写入http响应对象中,实现前端的文件下载功能,详细代码实现在这篇博客中:spring-mvc实现文件下载功能

    后来我想到,原因可能是前端请求后,后台有两个response响应:
     
    第一个response是将文件写到输出流中,第二个是controller返回到原来的页面。
     
    最终我找到了解决办法:controller结束后不指定返回的页面,也就是去掉controller的返回值,前端页面将保持不变,只会显示下载的文件。
     
    将controller方法改为无返回参数void,修改后的代码:
     
         @RequestMapping("/certificate_import/v_download_template.do")
         public void downloadTemplate(HttpServletRequest request,  HttpServletResponse response) {
               log.info("下载证书导入模板...");
               File template =  cmsCertificateImportMng.getCertificateDataTemplate();
               if (template == null) {
                    log.warn("没有获取到证书数据导入模板文件,下载失败");
                    return;
               }
               // 将文件流写入response
               FileDownloadUtils.writeFile2Response(response,  template);
         }
     
    这样下载时就再没有出现过上述的异常
     
  • 相关阅读:
    UDP通讯demo
    Git 修改已提交的commit注释
    git merge和git merge --no-ff的区别
    git常用命令
    阿里云域名证书申请流程
    IntelliJ IDEA常用快捷键总结
    宿主CentOS7环境下docker中rabbitMQ的安装
    宿主CentOS7环境下docker中nginx的安装
    docker常用命令
    CentOS7环境下docker安装
  • 原文地址:https://www.cnblogs.com/xhj123/p/12391457.html
Copyright © 2011-2022 走看看