在线实时生成excel文件下载

在线实时生成excel文件下载

       我正在的一个项目,需要实现在线实时生成 Excel文件供客户端下载的需求,最初考虑的是先在服务器端生成真实的文件,然后在客户端下载该文件。后来发现这样做不但性能不够好、速度较慢,而且还 要占用服务器空间。所以找到网上的例子采取了在服务器端生成文件输出流(ServletOutputStream),通过HttpServletResponse对象设 置相应的响应头,然后将此输出流传往客户端的方法实现。在实现过程中,用到了Apache组织的Jakarta开源组件POI,不过因为是用到webwork框架,而需求是大画面的其中一个按钮,目前只能考虑jsp来写画面,出现了输出流和jsp页面打开流出现冲突抛出异常。暂时的解决方法是return null,使它只是警告而不抛出异常。

一、首先,根据Excel表的特点,我编写了一个Excel表模型类ExcelModel,代码如下:
java 代码
 
  1. public class ExcelModel {  
  2.   
  3.     /** 
  4.      * 文件路径,这里是包含文件名的路径 
  5.      */  
  6.     protected String path;  
  7.   
  8.     /** 
  9.      * 工作表名 
  10.      */  
  11.     protected String sheetName;  
  12.   
  13.     /** 
  14.      * 表内数据,保存在二维的ArrayList对象中 
  15.      */  
  16.     protected ArrayList data;  
  17.   
  18.     /** 
  19.      * 数据表的标题内容 
  20.      */  
  21.     protected ArrayList header;  
  22.   
  23.     /** 
  24.      * 用于设置列宽的整型数组 这个方法在程序中暂未用到 适用于固定列数的表格 
  25.      */  
  26.     protected int[] width;  
  27.   
  28.     public ExcelModel() {  
  29.         path = "report.xls";  
  30.     }  
  31.   
  32.     /** 
  33.      * @return the data 
  34.      */  
  35.     public ArrayList getData() {  
  36.         return data;  
  37.     }  
  38.   
  39.     /** 
  40.      * @param data the data to set 
  41.      */  
  42.     public void setData(ArrayList data) {  
  43.         this.data = data;  
  44.     }  
  45.   
  46.     /** 
  47.      * @return the header 
  48.      */  
  49.     public ArrayList getHeader() {  
  50.         return header;  
  51.     }  
  52.   
  53.     /** 
  54.      * @param header the header to set 
  55.      */  
  56.     public void setHeader(ArrayList header) {  
  57.         this.header = header;  
  58.     }  
  59.   
  60.     /** 
  61.      * @return the path 
  62.      */  
  63.     public String getPath() {  
  64.         return path;  
  65.     }  
  66.   
  67.     /** 
  68.      * @param path the path to set 
  69.      */  
  70.     public void setPath(String path) {  
  71.         this.path = path;  
  72.     }  
  73.   
  74.     /** 
  75.      * @return the sheetName 
  76.      */  
  77.     public String getSheetName() {  
  78.         return sheetName;  
  79.     }  
  80.   
  81.     /** 
  82.      * @param sheetName the sheetName to set 
  83.      */  
  84.     public void setSheetName(String sheetName) {  
  85.         this.sheetName = sheetName;  
  86.     }  
  87.   
  88.     /** 
  89.      * @return the width 
  90.      */  
  91.     public int[] getWidth() {  
  92.         return width;  
  93.     }  
  94.   
  95.     /** 
  96.      * @param width the width to set 
  97.      */  
  98.     public void setWidth(int[] width) {  
  99.         this.width = width;  
  100.     }  
  101.   
  102. }  
二、编写一个下载接口ExcelDownLoad,定义基本的方法:
java 代码
 
  1. import java.io.IOException;  
  2. import java.util.List;  
  3.   
  4. import javax.servlet.http.HttpServletResponse;  
  5.   
  6. /** 
  7.  * 初始化要生成的Excel的表模型 
  8.  *  
  9.  * @param list List 填充了 Excel表格数据的集合 
  10.  * @param form ActionForm及其子类 
  11.  * @param excel ExcelModel Excel表的对象模型 
  12.  * @see ExcelModel 
  13.  * @throws Exception 
  14.  */  
  15. public interface ExcelDownLoad {  
  16.   
  17.     /** 
  18.      * 在已文件已存在的情况下,采用读取文件流的方式实现左键点击下载功能 
  19.      *  
  20.      * @param inPutFileName 读出的文件名 
  21.      * @param outPutFileName 保存的文件名 
  22.      * @param HttpServletResponse 
  23.      * @see HttpServletResponse 
  24.      * @throws IOException 
  25.      */  
  26.     public void downLoad(String inPutFileName, String outPutFileName, HttpServletResponse response) throws IOException;  
  27.   
  28.     /** 
  29.      * 初始化要生成的Excel的表模型 
  30.      *  
  31.      * @param list List 填充了 Excel表格数据的集合 
  32.      * @param form ActionForm及其子类 
  33.      * @param excel ExcelModel Excel表的对象模型 
  34.      * @see ExcelModel 
  35.      * @throws Exception 
  36.      */  
  37.     public ExcelModel createDownLoadExcel(List list, ExcelModel excel) throws Exception;  
  38.   
  39.     /** 
  40.      * 在已文件不存在的情况下,采用生成输出流的方式实现左键点击下载功能。 
  41.      *  
  42.      * @param outPutFileName 保存的文件名 
  43.      * @param out ServletOutputStream对象 
  44.      * @param downExcel 填充了数据的ExcelModel 
  45.      * @param HttpServletResponse 
  46.      * @see HttpServletResponse 
  47.      * @throws Exception 
  48.      */  
  49.     public void downLoad(String outPutFileName, ExcelModel downExcel, HttpServletResponse response) throws Exception;  
  50.   
  51. }  


三  公共基类BaseExcelDownLoad,并提供downLoad()方法的公共实现
java 代码
 
  1. public abstract class BaseExcelDownLoad implements ExcelDownLoad {  
  2.   
  3.     /** 
  4.      * 初始化要生成的Excel的表模型 
  5.      *  
  6.      * @param list List 填充了 Excel表格数据的集合 
  7.      * @param form ActionForm及其子类 
  8.      * @param excel ExcelModel Excel表的对象模型 
  9.      * @see ExcelModel 
  10.      * @throws Exception 
  11.      */  
  12.     public abstract ExcelModel createDownLoadExcel(List list, ExcelModel excel) throws Exception;  
  13.   
  14.     /** 
  15.      * 在已文件已存在的情况下,采用读取文件流的方式实现左键点击下载功能 
  16.      *  
  17.      * @param inPutFileName 读出的文件名 
  18.      * @param outPutFileName 保存的文件名 
  19.      * @param HttpServletResponse 
  20.      * @see HttpServletResponse 
  21.      * @throws IOException 
  22.      */  
  23.     public void downLoad(String inPutFileName, String outPutFileName, HttpServletResponse response) throws IOException {  
  24.   
  25.         // 打开指定文件的流信息  
  26.         InputStream is = new FileInputStream(inPutFileName);  
  27.         // 写出流信息  
  28.         int data = -1;  
  29.         OutputStream outputstream = response.getOutputStream();  
  30.   
  31.         // 清空输出流  
  32.         response.reset();  
  33.         // 设置响应头和下载保存的文件名  
  34.         response.setHeader("content-disposition", "attachment;filename=" + outPutFileName);  
  35.         // 定义输出类型  
  36.         response.setContentType("APPLICATION/msexcel");  
  37.   
  38.         while ((data = is.read()) != -1)  
  39.             outputstream.write(data);  
  40.         is.close();  
  41.         outputstream.close();  
  42.         response.flushBuffer();  
  43.   
  44.     }  
  45.   
  46.     /** */  
  47.     /** 
  48.      * 在文件不存在的情况下,采用生成输出流的方式实现左键点击下载功能。 
  49.      *  
  50.      * @param outPutFileName 保存的文件名 
  51.      * @param out ServletOutputStream对象 
  52.      * @param downExcel 填充了数据的ExcelModel 
  53.      * @param HttpServletResponse 
  54.      * @see HttpServletResponse 
  55.      * @throws Exception 
  56.      */  
  57.     public void downLoad(String outPutFileName, ExcelModel downExcel, HttpServletResponse response) throws Exception {  
  58.         
  59.             // 取得输出流  
  60.             OutputStream out = response.getOutputStream();  
  61.             // 清空输出流  
  62.             response.reset();  
  63.   
  64.             // 设置响应头和下载保存的文件名  
  65.             response.setHeader("content-disposition", "attachment;filename=" + outPutFileName);  
  66.             // 定义输出类型  
  67.             response.setContentType("APPLICATION/msexcel");  
  68.   
  69.             ExcelOperator op = new ExcelOperator();  
  70.             // out:传入的输出流  
  71.             op.WriteExcel(downExcel, out);  
  72.   
  73.             out.close();  
  74. //            ServletOutputStream os = response.getOutputStream();   
  75.             // out.clear();  
  76.             // out = pageContext.pushBody();  
  77.   
  78.             // 强行将响应缓存中的内容发送到目的地  
  79.             response.flushBuffer();  
  80.        
  81.   
  82.     }  
  操作类,进行生成下载文件流的操作

java 代码
 
  1. /** 
  2.  * 实现生成Excel文件的操作 
  3.  */  
  4. public class ExcelOperator {  
  5.   
  6.     /** 
  7.      * 将数据信息写入到Excel表文件,采取自建输出流的方式。 
  8.      *  
  9.      * @param excel ExcelModel Excel表的模型对象 
  10.      * @throws Exception 
  11.      */  
  12.     public void WriteExcel(ExcelModel excel) throws Exception {  
  13.   
  14.         try {  
  15.   
  16.             String file = excel.getPath();  
  17.   
  18.             // 新建一输出文件流  
  19.             FileOutputStream fOut = new FileOutputStream(file);  
  20.             BufferedOutputStream bf = new BufferedOutputStream(fOut);  
  21.   
  22.             HSSFWorkbook workbook = this.getInitWorkbook(excel);  
  23.   
  24.             // 把相应的Excel 工作簿存盘  
  25.             workbook.write(fOut);  
  26.             fOut.flush();  
  27.             bf.flush();  
  28.             // 操作结束,关闭文件  
  29.             bf.close();  
  30.             fOut.close();  
  31.             // System.out.println("Done!");  
  32.         } catch (Exception e) {  
  33.             // System.out.print("Failed!");  
  34.             throw new Exception(e.getMessage());  
  35.         }  
  36.   
  37.     }  
  38.   
  39.     /** 
  40.      * 将数据信息写入到Excel表文件 ,采取传入输出流的方式。 
  41.      *  
  42.      * @param excel Excel表的模型对象 
  43.      * @param out OutputStream 输出流 
  44.      * @throws Exception 
  45.      */  
  46.     public void WriteExcel(ExcelModel excel, OutputStream out) throws Exception {  
  47.         try {  
  48.             HSSFWorkbook workbook = this.getInitWorkbook(excel);  
  49.             workbook.write(out);  
  50.             out.close();  
  51.             // System.out.println("Done!");  
  52.         } catch (Exception e) {  
  53.             // System.out.println("Failed!");  
  54.             throw new Exception(e.getMessage());  
  55.         }  
实现按照具体的需求生成Excel表格文件流的类
java 代码
 
  1. /** 
  2.  * 根据需求的表格类或者结果集list 
  3.  *  
  4.  * @author Koala 
  5.  */  
  6. public class UserExcelDownLoad extends BaseExcelDownLoad {  
  7.   
  8.     public ExcelModel createDownLoadExcel(List list, ExcelModel excel) throws Exception {  
  9.         String titleStr = "ID;名称;性别;";  
  10.   
  11.         ArrayList data = new ArrayList();  
  12.   
  13.         Iterator ir = list.iterator();  
  14.         while (ir.hasNext()) {  
  15.   
  16.             ArrayList rowData = new ArrayList();  
  17.   
  18.             User user = (User) ir.next();  
  19.             rowData.add(user.getId());  
  20.             rowData.add(user.getName());  
  21.             rowData.add(user.getSex());  
  22.   
  23.             data.add(rowData);  
  24.   
  25.         }  
  26.   
  27.         String[] titles = titleStr.split(";");  
  28.   
  29.         /**//* 
  30.          * for(int i=0;i 
  31.          */  
  32.   
  33.         ArrayList header = new ArrayList();  
  34.         for (int i = 0; i < titles.length; i++) {  
  35.             header.add(titles[i]);  
  36.         }  
  37.   
  38.         // 设置报表标题  
  39.         excel.setHeader(header);  
  40.         // 设置报表内容  
  41.         excel.setData(data);  
  42.         return excel;  
  43.     }  
  44.   
  45. }  

最后在action部分
java 代码
 
  1. public class FileOutAction implements Action, ModelDriven {  
  2.   
  3.     private static Log log = LogFactory.getLog(FileOutAction.class);  
  4.   
  5.     public String execute() throws Exception {  
  6.         ExcelModel excel = new ExcelModel();  
  7.         excel.setSheetName("BidCost");  
  8.         ActionContext ctx = ActionContext.getContext();  
  9.         HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE);  
  10.         //写入到Excel格式输出流供下载  
  11.         try {  
  12.             // TODO 返回对象list  
  13.             List userList = new ArrayList();  
  14.             for (int i = 0; i <3; i++) {  
  15.                 User user = new User();  
  16.                 user.setId(i);  
  17.                 user.setName("1"+i);  
  18.                 user.setSex(i);  
  19.                 userList.add(user);  
  20.                   
  21.             }  
  22.              
  23.             //调用自编的下载类,实现Excel文件的下载  
  24.             ExcelDownLoad downLoad = new AgentInfoExcelDownLoad();  
  25.             ExcelModel downExcel = downLoad.createDownLoadExcel(userList, excel);  
  26.             //不生成文件,直接生成文件输出流供下载  
  27.             downLoad.downLoad("BidCost.xls", downExcel, response);  
  28.             response.resetBuffer();  
  29.             log.info("create Excel outputStream successful!");  
  30.   
  31.         } catch (Exception e) {  
  32.               
  33.             log.info("create Excel outputStream  failed!");  
  34.               
  35.         }  
  36. //TODO暂时的解决异常抛出  
  37.    return null;  
这是参照网上一个仁兄的提示写出的,如果跳转到本身画面,就会抛出流已经被打开的异常,所以暂时用了返回null,意味用servlet写画面太麻烦显示页面的东西了,而且有些不够统一,今天发现了,webwork可以返回none,不返回视图,问题终于解决了
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值