把动态表格生成excel用的库叫POI,从数据库提取出数据之后,利用POI可以产生一个stream。
大体步骤:
步骤一:从数据库读信息
步骤二:数据组装成excel
步骤三:用InputStream发回浏览器
数据流:
1.struts.xml中action配置
result:是“stream”vnd.ms-excel:文件类型是tomcat提供的
"contentDisposition">filename="AllUsers.xls":配置下载全都是附件形式,文件名以配置为准
"inputName">downloadFile:需要具体action中的get“downloadFile”
<action name="generateExcel" class="generateExcelAction">
<result name="success" type="stream"><!-- result是“stream”-->
<param name="contentType">application/vnd.ms-excel</param> <!--文件类型是tomcat提供的-->
<param name="contentDisposition">attachment;filename="AllUsers.xls"</param> <!--配置下载全都是附件形式,文件名以配置为准-->
<param name="inputName">downloadFile</param> <!--需要具体action中的get“downloadFile”-->
</result>
</action>
attachment;
临时文件“打开时”创建两次(下载时创建一次)tomcat/bin下:两个临时文件
要配置action:contentDisposition 要配成attachment(点开下载时,无论什么文件都会弹窗提示下载)
2.GenerateExcelAction
public InputStream getDownloadFile()
{
return this.service.getInputStream();
}
3.UserServiceImpl
这里边是生成excel的核心代码,组装好之后,要把生成的excel转换成InputStream类型还给action。action根据下载配置,把文件用附件的形式发给客户端,完成下载。
生成excel的过程是
1.创建sheet
2.由sheet创建:行
3.表头:short表示0号格
设置中文
4.迭代创建表格:
5.把表格写进 ByteArrayOutputStream 对象,再转换成InputStream 对象返还给action
public InputStream getInputStream()
{
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("sheet1");
HSSFRow row = sheet.createRow(0);
HSSFCell cell = row.createCell((short) 0);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("序号");
cell = row.createCell((short) 1);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("姓");
cell = row.createCell((short) 2);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("名");
cell = row.createCell((short) 3);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("年龄");
List<User> list = this.findAll();
for (int i = 0; i < list.size(); ++i)
{
User user = list.get(i);
row = sheet.createRow(i + 1);
cell = row.createCell((short) 0);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(i + 1);
cell = row.createCell((short) 1);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(user.getFirstname());
cell = row.createCell((short) 2);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(user.getLastname());
cell = row.createCell((short) 3);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(user.getAge());
}
ByteArrayOutputStream os = new ByteArrayOutputStream();
try
{
wb.write(os);
}
catch (IOException e)
{
e.printStackTrace();
}
byte[] content = os.toByteArray();
InputStream is = new ByteArrayInputStream(content);
return is;
}
4.用另一种思路:产生临时文件
上边产生excel的的方式没有用到临时文件,直接在内存里就都完成了。还有一种方法是利用临时文件保存excel表信息。
这种方法比较麻烦,首先是下载的文件名不能重复,否则多线程情况下就该互相覆盖掉了
String fileName = RandomStringUtils.randomAlphanumeric(10);
fileName = new StringBuffer(fileName).append(".xls").toString();
final File file = new File(fileName);
try
{
OutputStream os = new FileOutputStream(file);
wb.write(os);
os.close();
}
catch (Exception e)
{
e.printStackTrace();
}
InputStream is = null;
try
{
is = new FileInputStream(file);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
new Thread(new Runnable()
{
public void run()
{
try
{
Thread.sleep(15000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
file.delete();//删除临时文件
}
}).start();
return is;
而且产生的随机文件名的临时文件,还要自己估摸一个时间延迟删除:
new Thread(new Runnable()
{
public void run()
{
try
{
Thread.sleep(15000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
file.delete();//删除临时文件
}
}).start();
如果没删掉还有靠其他方法比如servlet启动时删除:
public void init() throws ServletException
{
File file = new File(".");
File[] subFiles = file.listFiles(new FileFilter()
{
public boolean accept(File pathname)
{
if(pathname.getName().endsWith("xls"))
{
return true;
}
return false;
}
}
);
for(File f : subFiles)
{
f.delete();
}
}
这个比较恶心,目前来看还是用第一种说的 在内存里ByteArrayOutputStream 完成吧,内存很紧张的时候可能才会用临时文件吧。