您的位置:首页 > 其它

在线实时生成excel文件下载

2008-08-31 00:00 337 查看

在线实时生成excel文件下载

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

一、首先,根据Excel表的特点,我编写了一个Excel表模型类ExcelModel,代码如下:
java 代码

public class ExcelModel {

/**
* 文件路径,这里是包含文件名的路径
*/
protected String path;

/**
* 工作表名
*/
protected String sheetName;

/**
* 表内数据,保存在二维的ArrayList对象中
*/
protected ArrayList data;

/**
* 数据表的标题内容
*/
protected ArrayList header;

/**
* 用于设置列宽的整型数组 这个方法在程序中暂未用到 适用于固定列数的表格
*/
protected int[] width;

public ExcelModel() {
path = "report.xls";
}

/**
* @return the data
*/
public ArrayList getData() {
return data;
}

/**
* @param data the data to set
*/
public void setData(ArrayList data) {
this.data = data;
}

/**
* @return the header
*/
public ArrayList getHeader() {
return header;
}

/**
* @param header the header to set
*/
public void setHeader(ArrayList header) {
this.header = header;
}

/**
* @return the path
*/
public String getPath() {
return path;
}

/**
* @param path the path to set
*/
public void setPath(String path) {
this.path = path;
}

/**
* @return the sheetName
*/
public String getSheetName() {
return sheetName;
}

/**
* @param sheetName the sheetName to set
*/
public void setSheetName(String sheetName) {
this.sheetName = sheetName;
}

/**
* @return the width
*/
public int[] getWidth() {
return width;
}

/**
* @param width the width to set
*/
public void setWidth(int[] width) {
this.width = width;
}

}
二、编写一个下载接口ExcelDownLoad,定义基本的方法:

java 代码

import java.io.IOException;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

/**
* 初始化要生成的Excel的表模型
*
* @param list List 填充了 Excel表格数据的集合
* @param form ActionForm及其子类
* @param excel ExcelModel Excel表的对象模型
* @see ExcelModel
* @throws Exception
*/
public interface ExcelDownLoad {

/**
* 在已文件已存在的情况下,采用读取文件流的方式实现左键点击下载功能
*
* @param inPutFileName 读出的文件名
* @param outPutFileName 保存的文件名
* @param HttpServletResponse
* @see HttpServletResponse
* @throws IOException
*/
public void downLoad(String inPutFileName, String outPutFileName, HttpServletResponse response) throws IOException;

/**
* 初始化要生成的Excel的表模型
*
* @param list List 填充了 Excel表格数据的集合
* @param form ActionForm及其子类
* @param excel ExcelModel Excel表的对象模型
* @see ExcelModel
* @throws Exception
*/
public ExcelModel createDownLoadExcel(List list, ExcelModel excel) throws Exception;

/**
* 在已文件不存在的情况下,采用生成输出流的方式实现左键点击下载功能。
*
* @param outPutFileName 保存的文件名
* @param out ServletOutputStream对象
* @param downExcel 填充了数据的ExcelModel
* @param HttpServletResponse
* @see HttpServletResponse
* @throws Exception
*/
public void downLoad(String outPutFileName, ExcelModel downExcel, HttpServletResponse response) throws Exception;

}

三 公共基类BaseExcelDownLoad,并提供downLoad()方法的公共实现

java 代码

public abstract class BaseExcelDownLoad implements ExcelDownLoad {

/**
* 初始化要生成的Excel的表模型
*
* @param list List 填充了 Excel表格数据的集合
* @param form ActionForm及其子类
* @param excel ExcelModel Excel表的对象模型
* @see ExcelModel
* @throws Exception
*/
public abstract ExcelModel createDownLoadExcel(List list, ExcelModel excel) throws Exception;

/**
* 在已文件已存在的情况下,采用读取文件流的方式实现左键点击下载功能
*
* @param inPutFileName 读出的文件名
* @param outPutFileName 保存的文件名
* @param HttpServletResponse
* @see HttpServletResponse
* @throws IOException
*/
public void downLoad(String inPutFileName, String outPutFileName, HttpServletResponse response) throws IOException {

// 打开指定文件的流信息
InputStream is = new FileInputStream(inPutFileName);
// 写出流信息
int data = -1;
OutputStream outputstream = response.getOutputStream();

// 清空输出流
response.reset();
// 设置响应头和下载保存的文件名
response.setHeader("content-disposition", "attachment;filename=" + outPutFileName);
// 定义输出类型
response.setContentType("APPLICATION/msexcel");

while ((data = is.read()) != -1)
outputstream.write(data);
is.close();
outputstream.close();
response.flushBuffer();

}

/** */
/**
* 在文件不存在的情况下,采用生成输出流的方式实现左键点击下载功能。
*
* @param outPutFileName 保存的文件名
* @param out ServletOutputStream对象
* @param downExcel 填充了数据的ExcelModel
* @param HttpServletResponse
* @see HttpServletResponse
* @throws Exception
*/
public void downLoad(String outPutFileName, ExcelModel downExcel, HttpServletResponse response) throws Exception {

// 取得输出流
OutputStream out = response.getOutputStream();
// 清空输出流
response.reset();

// 设置响应头和下载保存的文件名
response.setHeader("content-disposition", "attachment;filename=" + outPutFileName);
// 定义输出类型
response.setContentType("APPLICATION/msexcel");

ExcelOperator op = new ExcelOperator();
// out:传入的输出流
op.WriteExcel(downExcel, out);

out.close();
// ServletOutputStream os = response.getOutputStream();
// out.clear();
// out = pageContext.pushBody();

// 强行将响应缓存中的内容发送到目的地
response.flushBuffer();

}
操作类,进行生成下载文件流的操作

java 代码

/**
* 实现生成Excel文件的操作
*/
public class ExcelOperator {

/**
* 将数据信息写入到Excel表文件,采取自建输出流的方式。
*
* @param excel ExcelModel Excel表的模型对象
* @throws Exception
*/
public void WriteExcel(ExcelModel excel) throws Exception {

try {

String file = excel.getPath();

// 新建一输出文件流
FileOutputStream fOut = new FileOutputStream(file);
BufferedOutputStream bf = new BufferedOutputStream(fOut);

HSSFWorkbook workbook = this.getInitWorkbook(excel);

// 把相应的Excel 工作簿存盘
workbook.write(fOut);
fOut.flush();
bf.flush();
// 操作结束,关闭文件
bf.close();
fOut.close();
// System.out.println("Done!");
} catch (Exception e) {
// System.out.print("Failed!");
throw new Exception(e.getMessage());
}

}

/**
* 将数据信息写入到Excel表文件 ,采取传入输出流的方式。
*
* @param excel Excel表的模型对象
* @param out OutputStream 输出流
* @throws Exception
*/
public void WriteExcel(ExcelModel excel, OutputStream out) throws Exception {
try {
HSSFWorkbook workbook = this.getInitWorkbook(excel);
workbook.write(out);
out.close();
// System.out.println("Done!");
} catch (Exception e) {
// System.out.println("Failed!");
throw new Exception(e.getMessage());
}
实现按照具体的需求生成Excel表格文件流的类

java 代码

/**
* 根据需求的表格类或者结果集list
*
* @author Koala
*/
public class UserExcelDownLoad extends BaseExcelDownLoad {

public ExcelModel createDownLoadExcel(List list, ExcelModel excel) throws Exception {
String titleStr = "ID;名称;性别;";

ArrayList data = new ArrayList();

Iterator ir = list.iterator();
while (ir.hasNext()) {

ArrayList rowData = new ArrayList();

User user = (User) ir.next();
rowData.add(user.getId());
rowData.add(user.getName());
rowData.add(user.getSex());

data.add(rowData);

}

String[] titles = titleStr.split(";");

/**//*
* for(int i=0;i
*/

ArrayList header = new ArrayList();
for (int i = 0; i < titles.length; i++) {
header.add(titles[i]);
}

// 设置报表标题
excel.setHeader(header);
// 设置报表内容
excel.setData(data);
return excel;
}

}

最后在action部分

java 代码

public class FileOutAction implements Action, ModelDriven {

private static Log log = LogFactory.getLog(FileOutAction.class);

public String execute() throws Exception {
ExcelModel excel = new ExcelModel();
excel.setSheetName("BidCost");
ActionContext ctx = ActionContext.getContext();
HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE);
//写入到Excel格式输出流供下载
try {
// TODO 返回对象list
List userList = new ArrayList();
for (int i = 0; i <3; i++) {
User user = new User();
user.setId(i);
user.setName("1"+i);
user.setSex(i);
userList.add(user);

}

//调用自编的下载类,实现Excel文件的下载
ExcelDownLoad downLoad = new AgentInfoExcelDownLoad();
ExcelModel downExcel = downLoad.createDownLoadExcel(userList, excel);
//不生成文件,直接生成文件输出流供下载
downLoad.downLoad("BidCost.xls", downExcel, response);
response.resetBuffer();
log.info("create Excel outputStream successful!");

} catch (Exception e) {

log.info("create Excel outputStream failed!");

}
//TODO暂时的解决异常抛出
return null;
这是参照网上一个仁兄的提示写出的,如果跳转到本身画面,就会抛出流已经被打开的异常,所以暂时用了返回null,意味用servlet写画面太麻烦显示页面的东西了,而且有些不够统一,今天发现了,webwork可以返回none,不返回视图,问题终于解决了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: