之前项目中使用struts2实现文件导出,但是跟踪代码并没有理解这是怎么做到的。后来网上看了几个大神的文章才略有所悟,在此分享出来,望各位指点。
配置:
<package name="test" namespace="/test" extends="struts-default">
<action name="*" method="{1}" class="com.testAction">
<result name="download" type="stream">
<param name="contentType">application/octet-stream,text/csv;charset=UTF-8</param>
<param name="inputName">apendListInputStream</param>
<param name="contentDisposition">attachment;filename=${downFileName}</param>
<param name="bufferSize">10485760</param>
</result>
</action>
</package>
配置解释:
type="stream"
把一般内容输出到流
contentType
指定文件格式(内容类型,和互联网MIME标准中的规定类型一致,例如text/plain代表纯文本,text/xml表示XML,image/gif代表GIF图片,image/jpeg代表JPG图片)
contentDisposition
其中attachment 将会告诉浏览器下载该文件,filename 指定下载文件保有存时的文件名
bufferSize
下载缓冲区的大小
downFileName
要求action中必须有downFileName的一个属性,且提供了set get方法,在程序第一次发起对action的请求时给downFileName赋值,如(/test/exportFile.action)。
<param name="inputName">apendListInputStream</param>
参数inputName指定输入流的名称。和前面的文件名一样,Action里提供一个getApendListInputStream()的方法返回值是inputStream。
代码:
public class TestAction extends BaseAction{
private String downFileName;
public String getDownFileName() {
return downFileName;
}
public void setDownFileName(String downFileName) {
this.downFileName = downFileName;
}
public String exportFile() throws Exception{
//业务逻辑校验,比如导出数量大小限制等
//文件名命名
String name = "导出结果" + DateFormatUtils.format(new Date())+ ".csv";
downFileName = new String(name.getBytes("gbk"), "ISO8859-1");
return "download";
}
public InputStream getApendListInputStream() {
InputStream inputStream = null;
try {
//从数据库或其他地方获取要导出数据list
//list生成文件,这个地方如何生成文件,可以参考其他资料,我们只做strust2的逻辑,不纠结文件生成。
CSVWriter writer=null;
String[] titles = {"标题1","标题2","标题3","标题4"...};
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (Test ia : list) {
writer = new CSVWriter(new BufferedWriter(new OutputStreamWriter(baos, "GBK")));
writer.writeNext(titles);
writer.writeNext(ia);
}
inputStream=new ByteArrayInputStream(baos.toByteArray());
}catch (Exception e) {
log.error("StationMsgAction.getApendListInputStream is error", e);
}
return inputStream;
}
}
发送请求:/test/exportFile.action,即可导出文件。
有没有发现很神奇的事情,文件名和文件内容都是依据action中的方法生成的,文件名和文件内容调用哪个方法来生成,都是通过配置中的变量跟actiong中的方法做默认匹配的。虽然精简了代码,但是确实容易让人迷惑。