zoukankan      html  css  js  c++  java
  • 解决springmvc中文件下载功能中使用javax.servlet.ServletOutputStream out = response.getOutputStream();后运行出异常但结果正确的问题

    问题描述:

      在springmvc中实现文件下载功能一般都会使用javax.servlet.ServletOutputStream out = response.getOutputStream();封装下载的工具类,稍后我会分享该工具类。

    当使用了response.getOutputStream()后,由于在同一个请求中JSP或Servlet中同时调用了Response的getWriter和getOutputStream就会抛此异常,异常部分代码如下:

    严重: Servlet.service() for servlet jsp threw exception
    java.lang.IllegalStateException: getOutputStream() has already been called for this response
        at org.apache.catalina.connector.Response.getWriter(Response.java:678)
        at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:213)
        at javax.servlet.ServletResponseWrapper.getWriter(ServletResponseWrapper.java:104)
        at org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
        at org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)
        at org.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:186)
        at org.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:126)
        at org.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:80)
        at org.apache.jsp.download_jsp._jspService(download_jsp.java:103)
        at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
        at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
        at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:395)
        at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:339)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)

    网上有的解决办法都是基于jsp中有java代码的,但是如果想在springmvc的controller中使用时难免不太对应,经过我的摸索,由于下载文件大多数情况况下都是留在原页面,那么我试了一下将返回值设为void,结果巧妙解决了以上问题,特以此记录。

    测试的下载工具类如下:;

    
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStream;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class DownloadFile {
        /**
         * 下载文件,file 为文件位置
         */
        public static void downloadFile(String file, HttpServletRequest request,
                HttpServletResponse response) {
            try {
                File tempFile = new File(file.trim());
                String fileName = tempFile.getName();
                InputStream is = new FileInputStream(file);
                response.reset(); // 必要地清除response中的缓存信息
                request.setCharacterEncoding("UTF-8");
                response.setContentType("application/octet-stream; charset=utf-8");
                response.setHeader("Content-disposition", 
                                   "attachment;" + UserAgentUtil.encodeFileName(request, fileName));
                //response.setHeader("Content-Length", String.valueOf(fileLength));
                /*response.setHeader("Content-Disposition", "attachment; filename="
                        + java.net.URLEncoder.encode(fileName, "UTF-8"));*/
                javax.servlet.ServletOutputStream out = response.getOutputStream();
                byte[] content = new byte[1024];
                int length = 0;
                while ((length = is.read(content)) != -1) {
                    out.write(content, 0, length);
                }
                out.flush();
                out.close();
           is.close(); }
    catch (Exception e) { e.printStackTrace(); } } }

    测试的controller层代码如下:

    @RequestMapping(value = "/download.do")    
        public void downloadDetailPrice(//@RequestParam String id, 
                HttpServletRequest request, HttpServletResponse response) {
            String file = "D:\a.txt";
            DownloadFile.downloadFile(file,request,response);
                
        } 

     浏览器客户端防乱码工具类:

    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    
    import javax.mail.internet.MimeUtility;
    import javax.servlet.http.HttpServletRequest;
    
    
    /** @author  pangchao E-mail: pangchao620@163.com
     * @date : 2016年2月24日 上午11:27:26 
     * @Description : 文件下载时浏览器端防乱码编码工具类
     * @version 1.0 
     */
    public class UserAgentUtil {
    
        public static String encodeFileName(HttpServletRequest request, String fileName) {
            String userAgent = request.getHeader("User-Agent");
            String rtn = "";
            try {
                String new_filename = URLEncoder.encode(fileName, "UTF8");
                // 如果没有UA,则默认使用IE的方式进行编码,因为毕竟IE还是占多数的
                rtn = "filename="" + new_filename + """;
                if (userAgent != null) {
                    userAgent = userAgent.toLowerCase();
                    // IE浏览器,只能采用URLEncoder编码
                    if (userAgent.indexOf("msie") != -1) {
                        rtn = "filename="" + new_filename + """;
                    }
                    // Opera浏览器只能采用filename*
                    else if (userAgent.indexOf("opera") != -1) {
                        rtn = "filename*=UTF-8''" + new_filename;
                    }
                    // Safari浏览器,只能采用ISO编码的中文输出
                    else if (userAgent.indexOf("safari") != -1) {
                        rtn = "filename="" + new String(fileName.getBytes("UTF-8"), "ISO8859-1") + """;
                    }
                    // Chrome浏览器,只能采用MimeUtility编码或ISO编码的中文输出
                    else if (userAgent.indexOf("applewebkit") != -1) {
                        new_filename = MimeUtility.encodeText(fileName, "UTF8", "B");
                        rtn = "filename="" + new_filename + """;
                    }
                    // FireFox浏览器,可以使用MimeUtility或filename*或ISO编码的中文输出
                    else if (userAgent.indexOf("mozilla") != -1) {
                        rtn = "filename*=UTF-8''" + new_filename;
                    }
                }
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return rtn;
        }
    }
  • 相关阅读:
    BZOJ 1391: [Ceoi2008]order
    BZOJ 4504: K个串
    2019 年百度之星·程序设计大赛
    POJ 2398 Toy Storage (二分 叉积)
    POJ 2318 TOYS (二分 叉积)
    HDU 6697 Closest Pair of Segments (计算几何 暴力)
    HDU 6695 Welcome Party (贪心)
    HDU 6693 Valentine's Day (概率)
    HDU 6590 Code (判断凸包相交)
    POJ 3805 Separate Points (判断凸包相交)
  • 原文地址:https://www.cnblogs.com/superpang/p/5211224.html
Copyright © 2011-2022 走看看