今天郁闷了一把,特此立传!
先说下需求:下载服务器文件
实现方式:一是下载服务器文件。二是直接在服务器构造文件流输出。
我在这里的具体需求是查询后的结果通过excel下载。我在这里需要把查询后的结果构造成为一个excel文件,同时把它塞进输出流。昨天在测试翻页的时候发现,翻页后,第二页的多选异步调用失效,通过查页面源码发现,翻页操作后,页面丢失了对js文件的引用。通过对commandbutton的操作加上ajax标签,使之刷新范围在form里面,解决了这个问题。
可是,今天突然发现download不好用了。尝试了一天,终于看出了一点点门道(自己能力不是很好,呵呵)。原来,我的download按钮也被包裹在ajax标签内,所以,每次都会提示empty response(chrome下面)。而在glassfish控制台里面也会有
Caused by: java.lang.IllegalStateException: PWC3991: getOutputStream() has already been called for this response
这个异常报出!
火狐报的异常是XML数据没有准备好!
一起都是ajax标签包住commandbutton惹出的祸!
忘记把代码写上,代码来自网络,自己整理后,也应该贡献给网络:)
客户端调用这个函数:
public static <T> void download(String fileName,Collection<T> dataset){
ByteArrayOutputStream baos =downLoadWithExcel("test", "download", dataset, "yyyy-mm-dd");
//download.properties是你定义的表头和list元素的field对应关系,我做测试的是:User = user
Name = Name,user和name是两个属性,大写首字符是为了调反射方法的时候不用做首字母大写操作了
downloadAction(fileName,baos);
}
下面对两个函数说明下:
首先,获取excel流:
@title 用来说明生产的文件名
@fileName 由于项目特殊需求,类是由xsd生成的,通过反射拿不到field,这里通过定义properties文件,说明了各个field和要生成的表头之间对应的关系。而且这个field可以通过在类里面的getField方法获得这个字段的值,所以,我们定义了这个以文件。
@collection<T> 你传递进来的集合,想对这个集合生成excel文件,T类型的field在fileName定义的properties文件里都有说明了
@pattern 日期格式,一般就用“yyyy-MM-dd”就行
public static <T> ByteArrayOutputStream downLoadWithExcel(String title, String fileName, Collection<T> dataset, String pattern) {{
ByteArrayOutputStream baos = null;
BufferedOutputStream bos = null;
baos = new ByteArrayOutputStream();
bos = new BufferedOutputStream(baos);
// 声明一个工作薄
HSSFWorkbook workbook = new HSSFWorkbook();
// 生成一个表格
HSSFSheet sheet = workbook.createSheet(title);
// 设置表格默认列宽度为15个字节
sheet.setDefaultColumnWidth((short) 15);
// 生成一个样式
HSSFCellStyle style = workbook.createCellStyle();
// 设置这些样式
style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// 生成一个字体
HSSFFont font = workbook.createFont();
font.setColor(HSSFColor.VIOLET.index);
font.setFontHeightInPoints((short) 12);
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
// 把字体应用到当前的样式
style.setFont(font);
// 生成并设置另一个样式
HSSFCellStyle style2 = workbook.createCellStyle();
style2.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);
style2.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
style2.setBorderBottom(HSSFCellStyle.BORDER_THIN);
style2.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style2.setBorderRight(HSSFCellStyle.BORDER_THIN);
style2.setBorderTop(HSSFCellStyle.BORDER_THIN);
style2.setAlignment(HSSFCellStyle.ALIGN_CENTER);
style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
// 生成另一个字体
HSSFFont font2 = workbook.createFont();
font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
// 把字体应用到当前的样式
style2.setFont(font2);
// 声明一个画图的顶级管理器
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
// 定义注释的大小和位置,详见文档
HSSFComment comment = patriarch.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short) 4, 2, (short) 6, 5));
// 设置注释内容
comment.setString(new HSSFRichTextString("可以在POI中添加注释!"));
// 设置注释作者,当鼠标移动到单元格上是可以在状态栏中看到该内容.
comment.setAuthor("leno");
//产生表格标题行
HSSFRow row = sheet.createRow(0);
ResourceBundle resource = ResourceBundle.getBundle(fileName);
Set<String> keys = resource.keySet();
int i = 0;
for (String key : keys) {
HSSFCell cell = row.createCell(i);
cell.setCellStyle(style);
HSSFRichTextString text = new HSSFRichTextString();
cell.setCellValue(resource.getString(key));
i++;
}
//遍历集合数据,产生数据行
Iterator<T> it = dataset.iterator();
int index = 0;
while (it.hasNext()) {
index++;
row = sheet.createRow(index);
T t = (T) it.next();
//利用反射,根据javabean属性的先后顺序,动态调用getXxx()方法得到属性值
int j = 0;
for (String key : keys) {
HSSFCell cell = row.createCell(j);
cell.setCellStyle(style2);
String getMethodName = "get"
+ key;
try {
Class tCls = t.getClass();
Method getMethod = tCls.getMethod(getMethodName,
new Class[]{});
Object value = getMethod.invoke(t, new Object[]{});
//判断值的类型后进行强制类型转换
String textValue = null;
if (value instanceof Boolean) {
boolean bValue = (Boolean) value;
textValue = "true";
if (!bValue) {
textValue = "false";
}
} else if (value instanceof Date) {
Date date = (Date) value;
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
textValue = sdf.format(date);
} else {
//其它数据类型都当作字符串简单处理
textValue = value.toString();
System.out.println(textValue);
}
//如果不是图片数据,就利用正则表达式判断textValue是否全部由数字组成
if (textValue != null) {
Pattern p = Pattern.compile("^\\d+(\\.\\d+)?$");
Matcher matcher = p.matcher(textValue);
if (matcher.matches()) {
//是数字当作double处理
cell.setCellValue(Double.parseDouble(textValue));
} else {
HSSFRichTextString richString = new HSSFRichTextString(textValue);
HSSFFont font3 = workbook.createFont();
font3.setColor(HSSFColor.BLUE.index);
richString.applyFont(font3);
cell.setCellValue(richString);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//清理资源
}
j++;
}
}
try {
workbook.write(bos);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
}
return baos;
}
}
获得生成的excel流后,就可以通过弟啊用downloadAction方法了
public static void downloadAction(String fileName,ByteArrayOutputStream baos) {
try {
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
response.setHeader("Content-disposition", "attachment; filename=" + fileName + ".xls"); //不是内嵌显示(inline),而是作为附件下载
response.setContentLength(baos.size());
response.setContentType("application/vnd.ms-excel");
//response.reset();这个方法千万不要用,会出错的!
ServletOutputStream sos = response.getOutputStream();
baos.writeTo(sos);
sos.flush();
baos.close();
} catch (IOException ex) {
logger.debug(ex);
}
}
分享到:
相关推荐
JSF2.0标签手册DQSV
Mojarra JSF 2.0库文件。开发JSF2.0 Web应用时放在lib目录下。
JSF 2.0 Programming Cookbook JSF PAGE Ajax JSF J2EE Eclipse IDE support
JSF2.0实战 - 6、TextBox示例代码
jSF2.0与Spring整合实例+教程
jsf2.0的开发配置说明,和简单的配置例子,开发例子,及JSF2.0的所有标签的详细分析。
JSF2.0实战 - 10、自定义Ajax更新方式源代码
JSF2.0_开发入门JSF2.0_开发入门JSF2.0_开发入门JSF2.0_开发入门JSF2.0_开发入门JSF2.0_开发入门JSF2.0_开发入门
jsf2.0+richfaces4.2.3需要的jar包
使用 Netbeans 开发JSF 2.0,使用Primefaces 及JPA ,一步一步指导如何开发
个人收集的JSF2.0的开发简介 共64页 讲解了绝大部份JSF2.0的新特性
JSF2.0系列简介.doc 和 文档想配的源代码,后面的AJAX的例子做,留给你们自己完成.希望能帮助到大家
在Java EE 6中使用JSF 2.0简化页面制作 在Java EE 6中使用JSF 2.0简化页面制作 在Java EE 6中使用JSF 2.0简化页面制作
放一下lib在这里,供学习JSF 2.0的朋友们下载,免得大家跑到国外去下载
JSF JSF2.0 Ajax javaweb JSF与Ajax交互实现
JSF2.0 Tutorial,总共18个章节,详细介绍了jsf2.0的overview, new feature, managedbean, el, ajax,spring集成等,并配source code.由于文件比较大切分成了3个压缩包。
jsf2.0 hibernate3.2 spring2.5环境所有jar包,包括richfaces mysql log4j 在eclipse里手动配置环境经常会因jar出现种种问题,我把完整的jsf2.0 spring2.5 hibernate3整合所有jar传上来希望有用 如果有需要我会传上一...
jsf2.0 dataTable单行修改例子,包含了jsf dataTable修改一行数据的方法
JSF2.0 Tutorial,总共18个章节,详细介绍了jsf2.0的overview, new feature, managedbean, el, ajax,spring集成等,并配source code.由于文件比较大切分成了3个压缩包。
JSF2.0 Tutorial,总共18个章节,详细介绍了jsf2.0的overview, new feature, managedbean, el, ajax,spring集成等,并配source code.由于文件比较大切分成了3个压缩包。