zoukankan      html  css  js  c++  java
  • spring mvc的excel报表文件下载时流的冲突解决

    在jsp或者在servlet中有时要用到 response.getOutputStream(),但是此时会在后台报这个错误java.lang.IllegalStateException: getOutputStream() has already been called for this respons,这问题困扰了我好久都没解决,最近这个项目中我又遇到了,下定决心一定要解决掉,最后终于让我给找到解决的方法了,这个异常时因为 response.getOutputStream()跟response.getWriter()相冲突造成的,呵呵!现在记录下,发出来和大家共享 下,希望能帮到遇到同样问题的朋友们,解决方法如下:

        out.clearBuffer(); 

        out = pageContext.pushBody();

    在调用response.getOutputStream()之前加上上面两代码,就ok了!

     

    上面的是网上流行的解决方案, 在jsp中<% %>写入红色代码;

     

    我的解决方案是将改下载方法的返回值为void或return时为null都可以, 我是用的是spring mvc 在Struts中的方法通常也会带有返回值;

    code:

     

    package com.piaomeng.b2bv5.stat.controller;
    
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.poi.hssf.usermodel.HSSFCell;
    import org.apache.poi.hssf.usermodel.HSSFCellStyle;
    import org.apache.poi.hssf.usermodel.HSSFFont;
    import org.apache.poi.hssf.usermodel.HSSFRow;
    import org.apache.poi.hssf.usermodel.HSSFSheet;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import com.piaomeng.b2bv5.core.auth.AuthPassport;
    import com.piaomeng.b2bv5.stat.service.IBStatisticsService;
    import com.piaomeng.b2bv5.stat.vo.PasteCount;
    import com.piaomeng.b2bv5.stat.vo.PasteCountExcel;
    import com.piaomeng.b2bv5.util.PrintWriterUtil;
    
    @Controller
    @Scope("prototype")
    @RequestMapping("/statistics")
    public class StickPointController {
        @Autowired
        private IBStatisticsService statisticsService;
        private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        
        /**销售跳转链接*/
        @RequestMapping("/skipTieDianXsIndex")
        @AuthPassport(auth="/statistics/skipTieDianXsIndex", check=false)
        public String skipTieDianXsIndex(Map<String,Object> map){
            map.put("beginDate", sdf.format(new Date()));
            map.put("endDate", sdf.format(new Date()));
            return "/jsp/stat/stickPointStatistics_xs";
        }
        /**销售显示主要方法*/
        @RequestMapping("/selectTieDianXsList")
        @AuthPassport(auth="/statistics/selectTieDianXsList", check=false)
        public String selectTieDianXsList(HashMap<String,Object> map, String salesId,
                String beginDate, String endDate){
            map.put("beginDate", beginDate);
            map.put("endDate", endDate);
            map.put("salesId", salesId);
            // 根据日期判断是上半年/下半年分别查询, 例如2015-09-03 只截取月 09;
            String currentMonth = beginDate.substring(5, 7);// 开始日期和结束日期的月份相同, 页面js已经校验;
            String[] first_half_year = {"01", "02", "03", "04", "05", "06"};
            String[] last_half_year = {"07", "08", "09", "10", "11", "12"};
            List<String> fhy = Arrays.asList(first_half_year);
            List<String> lhy = Arrays.asList(last_half_year);
            
            // 设置动态表名 1-6 月 t_od_border1501 7-12 月 t_od_border1507; 上半年设置表后缀为01 (1-6月)下半年设置表后缀为07 (7-12月);
            String tableName = null;
            if (fhy.contains(currentMonth)) {// 上半年;
                tableName = "T_OD_BORDER" + beginDate.substring(2, 4) + "01";
            }
            if (lhy.contains(currentMonth)) {// 下半年;
                tableName = "T_OD_BORDER" + beginDate.substring(2, 4) + "07";
            }
            map.put("border", tableName);
            map.put("orderdesc", "T_OD_ORDERDESC".concat(beginDate.substring(2, 4)).concat(currentMonth));
            map.put("passinfo", "T_OD_PASSINFO".concat(beginDate.substring(2, 4)).concat(currentMonth));
            List<PasteCount> pasteCounts = statisticsService
                    .selectPasteCountList(map);
            // 计算总计;
            PasteCount pc = null;
            int ticketCount = 0;
            double buyPrice = 0.00, levelPrice = 0.00;
            if (pasteCounts.size() > 0 && pasteCounts != null) {
                for (Iterator<PasteCount> iterator = pasteCounts.iterator(); iterator.hasNext();) {
                    PasteCount item = iterator.next();
                    ticketCount += item.getTicketCount();
                    buyPrice += item.getBuyPrice();
                    levelPrice += item.getLevelPrice();
                }
                pc = new PasteCount();
                pc.setUsername("全部");
                pc.setTicketCount(ticketCount);
                pc.setBuyPrice(buyPrice);
                pc.setLevelPrice(levelPrice);
            }
            // end
            map.put("pasteCounts", pasteCounts);
            map.put("totalCount", pc);
            return "/jsp/stat/stickPointStatistics_xs";
        }
        /**销售的下载贴点明细statistics/selectTieDianXsListDownload*/
        @RequestMapping("/selectTieDianXsListDownload")
        @AuthPassport(auth="/statistics/selectTieDianXsListDownload", check=false)
        public String selectTieDianXsListDownload(HashMap<String,Object> map, String salesId,
                String beginDate, String endDate, HttpServletResponse response){
            try {
                map.put("beginDate", beginDate);
                map.put("endDate", endDate);
                map.put("salesId", salesId);
                // 根据日期判断是上半年/下半年分别查询, 例如2015-09-03 只截取月 09;
                String currentMonth = beginDate.substring(5, 7);// 开始日期和结束日期的月份相同, 页面js已经校验;
                String[] first_half_year = {"01", "02", "03", "04", "05", "06"};
                String[] last_half_year = {"07", "08", "09", "10", "11", "12"};
                List<String> fhy = Arrays.asList(first_half_year);
                List<String> lhy = Arrays.asList(last_half_year);
                
                // 设置动态表名 1-6 月 t_od_border1501 7-12 月 t_od_border1507; 上半年设置表后缀为01 (1-6月)下半年设置表后缀为07 (7-12月);
                String tableName = null;
                if (fhy.contains(currentMonth)) {// 上半年;
                    tableName = "T_OD_BORDER" + beginDate.substring(2, 4) + "01";
                }
                if (lhy.contains(currentMonth)) {// 下半年;
                    tableName = "T_OD_BORDER" + beginDate.substring(2, 4) + "07";
                }
                map.put("border", tableName);
                map.put("orderdesc", "T_OD_ORDERDESC".concat(beginDate.substring(2, 4)).concat(currentMonth));
                map.put("passinfo", "T_OD_PASSINFO".concat(beginDate.substring(2, 4)).concat(currentMonth));
                List<PasteCountExcel> pasteCountExcels = statisticsService
                        .selectTieDianXsListDownload(map);
                if (pasteCountExcels.size() > 0 && pasteCountExcels != null) {// 如果数据不为空则写入Excel文件后下载;
                    // 导出数据到报表;
                    exportTdmxXs(selectListHeaderXs(), pasteCountExcels, response);
                }else{// 如果数据为空则不进行下载直接显示页面提示信息;
                    map.put("tips", "当前数据为空!");
                    return "/jsp/stat/stickPointStatistics_xs";
                }
            } catch (Exception e) {
                PrintWriterUtil.writeToClient(response, "下载失败!");
                e.printStackTrace();
            }
            return null;
        }
        
        //销售报表贴点具体方法;
        public static void exportTdmxXs(List<String> headers, List<PasteCountExcel> contents, HttpServletResponse response){
            try {
                if (contents != null && contents.size() > 0) {
                    String xlsFile = "tdmx_xs" + new SimpleDateFormat("yyyyMMddHHssmm") + ".xls";
                    HSSFWorkbook wb = new HSSFWorkbook();
                    HSSFSheet sheet = wb.createSheet("销售贴点明细");
    
                    HSSFRow nRow = null;
                    HSSFCell nCell   = null;
                    
                    // 表头
                    nRow = sheet.createRow(0);// 表头(共一行);
                    for(int i = 0; i < headers.size(); i++){// 共?列; 日期, 采购ID, 所属人, 所属城市, 级别贴点订单票数, 级别贴点金额;
                        // 为列 创建单元格对象
                        nCell = nRow.createCell(i);
                        // 为列 创建单元格对象设置内容
                        nCell.setCellValue(headers.get(i));
                        /** 为表头每个列设置颜色*/
                        HSSFCellStyle curStyle = wb.createCellStyle();
                        //curStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);// 单元格内容居中对齐
                        curStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
                        curStyle.setFillForegroundColor((short) 10);
                        //********
                        curStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//粗实线
                        curStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
                        curStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
                        curStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
                        // 设置字体;
                        HSSFFont curFont = wb.createFont();                                //设置字体
                        curFont.setFontName("微软雅黑");                                    //设置英文字体
                        curFont.setCharSet(HSSFFont.DEFAULT_CHARSET);                    //设置中文字体,那必须还要再对单元格进行编码设置
                        curFont.setFontHeightInPoints((short)12);                        //字体大小
                        curFont.setBoldweight((short)5);
                        curStyle.setFont(curFont);
                        //********
                        nCell.setCellStyle(curStyle);
                        /**end*/
                    }
                    // 表内容
                    for (int i = 0; i < contents.size(); i++) {
                        nRow = sheet.createRow(i+1);    // 表内容(动态行);
                        for(int j = 0; j < headers.size(); j++){// 共?列; 日期, 采购ID, 所属人, 所属城市, 级别贴点订单票数, 级别贴点金额;
                            // 为列 创建单元格对象
                            nCell = nRow.createCell(j);
                            // 为列 创建单元格对象设置内容
                            if ("日期".equals(headers.get(j))) {
                                sheet.setColumnWidth(j, 3000);
                                nCell.setCellValue(contents.get(i).getLastUpdateTime());
                            }else if ("采购ID".equals(headers.get(j))) {
                                nCell.setCellValue(contents.get(i).getBuyerId());
                            }else if ("所属人".equals(headers.get(j))) {
                                nCell.setCellValue(contents.get(i).getUsername());
                            }else if ("所属城市".equals(headers.get(j))) {
                                sheet.setColumnWidth(j, 3000);
                                nCell.setCellValue(contents.get(i).getBuyerCity());
                            }else if ("级别贴点订单票数".equals(headers.get(j))) {
                                sheet.setColumnWidth(j, 5000);
                                nCell.setCellValue(contents.get(i).getTicketCount());
                            }else if ("级别贴点金额".equals(headers.get(j))) {
                                sheet.setColumnWidth(j, 4000);
                                nCell.setCellValue(contents.get(i).getLevelPrice());
                            }
                            // 为该列设置背景色 start
                            HSSFCellStyle curStyle = wb.createCellStyle();
                            curStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);// 单元格内容居中对齐
                            curStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
                            curStyle.setFillForegroundColor((short) 40);
                            //********
                            curStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
                            curStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
                            curStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
                            curStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
                            //********
                            nCell.setCellStyle(curStyle);
                            // end
                        }
                    }
                    
                    //设置样式
                    //nCell.setCellStyle(leftStyle(wb));
    
                    // 准备下载;
                    response.reset();
                    response.addHeader("Content-Disposition", "attachment;filename=" + xlsFile);
                    response.setContentType("application/octet-stream");// .*( 二进制流,不知道下载文件类型), 不知道下载的类型具体是什么可以使用这个;
                    //response.setContentType("application/vnd.ms-excel");// 定义输出类型
                    
                    ServletOutputStream sos = response.getOutputStream();
                    wb.write(sos);
                    sos.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static List<String> selectListHeaderXs(){
            //日期, 采购ID, 所属人, 所属城市, 级别贴点订单票数, 级别贴点金额;
            List<String> lists = new ArrayList<String>();
            lists.add("日期");
            lists.add("采购ID");
            lists.add("所属人");
            lists.add("所属城市");
            lists.add("级别贴点订单票数");
            lists.add("级别贴点金额");
            return lists;
        }
        
    }

     

    点击下载时控制台不会报错:

      java.lang.IllegalStateException: getOutputStream() has already been called for this response

    没报错吧!:-D:)

    完成;

     

     

  • 相关阅读:
    PHP面向对象(一)
    Linux(九)LNMP环境Nginx服务器
    Linux(八)Apache服务器
    [转]PHP高手干货分享:不能不看的50个细节!
    Linux(七)LAMP环境搭建
    Linux(六)Samba服务器与防火墙
    Linux(五)服务和进程管理
    Linux(四)用户和用户组管理
    Linux(三)安装包
    Linux(二)Linux常用命令
  • 原文地址:https://www.cnblogs.com/YingYue/p/4861681.html
Copyright © 2011-2022 走看看