Struts2从事工作以来很少用到,用的最多就是Spring。最近公司需要做一个导出Excel功能,Excel的功能我都已经写好了并测试通过了可以正常生成Excel文件,可是在页面下载的时候,始终不能够下载,response我也添加了response.setContentType("octets/stream");response.addHeader("Content-Disposition", "attachment;filename=test.xls");可是还是不行,最后发现,原来文件下载必须要用form表单提交请求或者a标签,用ajax发送请求不行(以前没有做过文件下载功能,只做过文件上传工)。今天写 这个博客的目的在于将Struts2的文件下载怎么做以及配置文件怎么写,交代说明下,为了以后方便查看,正所谓好记性不如烂笔头。(代码没有进行优化,写的有点丑,不管了先把功能实现了,然后在慢慢优化代码)
//Action代码
package com.maimai.back_action;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.springframework.beans.factory.annotation.Autowired;
import com.maimai.db_bean.Order;
import com.maimai.engine.DealEngine;
import com.maimai.test.ExportExcelUtil;
import com.maimai.util.Util;
import com.opensymphony.xwork2.ActionSupport;
public class ExportExcelAction extends ActionSupport implements ServletRequestAware{
/**
*
*/
private static final long serialVersionUID = 456198271927643347L;
private HttpServletRequest request;
@Autowired
private DealEngine dealEngine;
private InputStream DownloadExcel; //Struts配置文件中有用到
private String fileName; //Struts配置文件中有用到
/**
*
* @return
* @throws IOException
*/
public InputStream getDownloadExcel() throws IOException{
HttpServletResponse response = Util.getHttpServletResponse();
response.setContentType("octets/stream");
response.addHeader("Content-Disposition", "attachment;filename=test.xls");
OutputStream out = response.getOutputStream();
Map<String,Object> params = new HashMap<String, Object>();
params = Util.request2Map(request, params);
List<Order> orders = dealEngine.getOrderService().getOrderDao().findOrdersByConditionMapForBack(params);
String[] header = {"id","code","userId","receiveUserName","receiveUserTelNum","address","payMode","orderTime","status","type","sendTime","valid","totalMoney","totalGiveJifen","hurryMoney","sendMoney","payTool"};
//获取Excel输入流
InputStream in = new ExportExcelUtil<Order>().exportExcel("test", orders, header, out, "yyyy-MM-dd");
//将流输出到客户端
int b = 0;
byte[] buffer = new byte[1024];
while(b != -1){
b = in.read(buffer);
out.write(buffer, 0, b);
out.flush();
}
out.close();
System.out.println("excel导出成功!");
// String fileName = "test.xls";
// OutputStream out1 = new FileOutputStream(Util.getRootPath()+fileName);
// new ExportExcelUtil<Order>().exportExcel("test", orders, header, out1, "yyyy-MM-dd");
// out1.close();
return in;
}
/**
* 前端页面发送的请求在这
* @return
* @throws IOException
*/
public String DownloadFile() throws IOException{
fileName = "test.xls";
DownloadExcel = getDownloadExcel(); //这步骤很重要,关系到struts配置文件中inputName
return "success";
}
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
}
//Excel生成代码
package com.maimai.test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
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.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
public class ExportExcelUtil<T> {
/**
*
* @param title 标题
* @param dataset 数据集
* @param header 列标题
* @param out
*/
public InputStream exportExcel(String title,List<T> dataset,String header[],OutputStream out,String pattern){
// 声明一个工作薄
HSSFWorkbook workbook = new HSSFWorkbook();
// 生成一个表格
HSSFSheet sheet = workbook.createSheet(title);
// 设置表格默认列宽度为15个字节
sheet.setDefaultColumnWidth(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);
//产生表格标题行
HSSFRow row = sheet.createRow(0);
for(short i = 0; i < header.length; i++){
HSSFCell cell = row.createCell(i);
cell.setCellStyle(style);
HSSFRichTextString text = new HSSFRichTextString(header[i]);
cell.setCellValue(text);
}
//遍历集合数据,产生数据行
Iterator<T> it = dataset.iterator();
int index = 0;
while (it.hasNext()) {
index++;
row = sheet.createRow(index);
T t = (T) it.next();
//利用反射,根据javabean属性的先后顺序,动态调用getXxx()方法得到属性值
Field[] fields = t.getClass().getDeclaredFields();
for (short i = 0; i < fields.length; i++) {
HSSFCell cell = row.createCell(i);
cell.setCellStyle(style2);
Field field = fields[i];
String fieldName = field.getName();
String getMethodName = "get"
+ fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);
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 Date) {
Date date = (Date) value;
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
textValue = sdf.format(date);
} else{
//其它数据类型都当作字符串简单处理
if(null == value){
textValue="";
}else{
textValue = value.toString();
}
}
//如果不是图片数据,就利用正则表达式判断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 (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//清理资源
}
}
}
ByteArrayOutputStream os = new ByteArrayOutputStream();
try
{
workbook.write(os);
}
catch (IOException e)
{
e.printStackTrace();
}
byte[] content = os.toByteArray();
InputStream is = new ByteArrayInputStream(content);
return is;
}
}
<!-- Excel文件下载 -->
<action name="backexportExcel*" class="com.maimai.back_action.ExportExcelAction" method="{1}">
<result name="success" type="stream">
<param name="contentType">application/vnd.ms-excel</param>
<param name="contentDisposition">attachment;filename="test.xls"</param> <!-- 这里filename可以是动态的,${fileName} 这个值的获取来源请求方法中fileName(注:为了区分我将这里的N大小写区分了,目的在于知道这个fileName值在哪来的,当然你也可以写成${attachName},那么请求的那个方法必须要有attchName这个变量并为其赋值) -->
<param name="inputName">DownloadExcel</param><!-- 这里也可以动态写,我都没有写,这里<span style="font-family: Arial, Helvetica, sans-serif;">DownloadExcel就是Action中private InputStream </span><span style="font-family: Arial, Helvetica, sans-serif;">DownloadExcel</span> -->
</result>
</action>
//这里我没有生成一个文件存放在服务器中,都是以流的形式,先返回一个输入流,然后通过输出流将流输出到客户端