这是请求方法,一般的action,controller,特殊的地方是不要有返回值,因为打印输出的文档就是输出
@Action(value = "/jz/card/exportDoc", results = { @Result(name = "success",type = "stream")})
public void exportDoc() throws Exception{businessid = (String)session.get("businessid");
Long bid=(businessid==null?0:Long.valueOf(businessid));
list=redemptionCardService.getCardByStatus(status,printStatus,bid);
//修改希望保留到数据库的字段//此处修改卡券的打印状态
for (RedemptionCard rcard : list)
{
rcard.setPrintStatus(1);
}
redemptionCardService.batchSave(list);
//下面处理不希望保留到数据库的字段,但是因为要打印到word需要特殊处理的内容,譬如希望抓取本地图片绝对路径
root=PropertyHolder.get().getServerPath();
/* for (RedemptionCard rcard : list)
{
StringBuilder sb=new StringBuilder();
//upload文件夹相对目录
String ewm=rcard.getEwm();
//获取tomcat项目目录的webapps根目录的root,然后添加到相对路径前面
sb.append(root).append(ewm);
rcard.setEwm(sb.toString());
}*/
//创建一个导出word文档工具对象
ExportDoc exportDoc = new ExportDoc();
//要填入模本的数据对象,放在map中
Map<String, Object> rootMap = new HashMap<String, Object>();
rootMap.put("list", list);
rootMap.put("root", root);
String ftlModelPath="/com/canyou/template/";//模板类所在包路径
String ftlName="cardExport.ftl";//导出word形式的ftl模板名称
//传入参数、工具对象将创建word文档
exportDoc.create(rootMap,response,ftlModelPath,ftlName);
}
下面是关键的导出工具类exportDoc 封装了转换的方法
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import com.thoughtworks.xstream.core.util.Base64Encoder;
import freemarker.template.Configuration;
import freemarker.template.Template;
/** @Title: create 创建并导出word文档,response输出到浏览器
* @author 杜闪
* @ClassName:ExportDoc
* @Description: 导出提货卡二维码到word文档中,
* @date:2017-5-11 下午3:52:12
* @version 1.0
*/
public class ExportDoc {
private Configuration configuration = null;
//构造函数初始化配置
public ExportDoc() {
configuration = new Configuration();
configuration.setDefaultEncoding("UTF-8");
}
/**
*
* @Title: create 创建word文档,response输出到浏览器
* @Description: @param 说明:(注意dataMap里存放的数据Key值要与ftl模板中的参数相对应,
* @ftlModelPath ftl模板的类路径,一般以ftl后缀结束
* @ftlName ftl模板名称)
* @param @dataMap
* @param @param response
* @param @ftlModelPath
* @param @ftlName
* @param @throws Exception
* @return Boolean
* // 模板放在com.canyou.template包下面,通过ClassForTemplateLoading装载
//configuration.setDirectoryForTemplateLoading(new File("/views/redemption/"));//存放在文档目录里装载也可以
//自己在项目中放入模板位置,完整的包名称,设置要装载的模板路径
* @throws
*/
public void create(Map<String, Object> rootMap, HttpServletResponse response,String ftlModelPath,String ftlName)
throws Exception {
//设置要装载的模板名称
configuration.setClassForTemplateLoading(this.getClass(), ftlModelPath);
Template template = configuration.getTemplate(ftlName);
//生成文件名称,日期字符串
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
String fileName = sdf.format(new Date());
File outFile = new File(fileName.replace(".", "")+".doc");
if (!outFile.exists()) {
outFile.createNewFile();
}
//输出路径
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"));
//模板处理数据
template.process(rootMap, out);
out.close();
//导出时有界面,可选择下载路径,response输出
response.addHeader("Content-Disposition", "attachment;filename=" + new String(outFile.getName().getBytes("utf-8"), "utf-8"));
response.setContentType("application/msword");
OutputStream out1 = null;
InputStream in = null;
try {
in = new FileInputStream(outFile);
BufferedInputStream bis = new BufferedInputStream(in);
//response输出流
out1 = response.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(out1);
byte[] buff = new byte[1024];
int bytesRead=0;
while (-1 != (bytesRead = bis.read(buff))) {
bos.write(buff, 0, bytesRead);
}
bos.flush();
bos.close();
bis.close();
} catch (Exception e) {
e.printStackTrace();
}
finally {
if (out1 != null)
out1.close();
if (in != null)
in.close();
}
}
/**
*
* @Title: getImageString
* @Description: 将本地、网络图片转换成BASE64字符串
* @param @param filename
* @param @return
* @param @throws IOException
* @return String
* @throws
*/
public static String getImageString(String imageUrl) throws IOException {
InputStream in = null;
InputStream dis = null;
byte[] data = null;
try {
//方法一、将网络图片导入word
/*URL url = new URL(imageUrl);
//打开网络输入流
URLConnection conn = url.openConnection();
//设置超时间为3秒
//conn.setConnectTimeout(3*1000);
//防止屏蔽程序抓取而返回403错误
//conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
//得到输入流
InputStream inputStream = conn.getInputStream();
//获取自己数组
data = readInputStream(inputStream); */
//方法二、将本地图片导入word,打开本地输入流
in = new FileInputStream(imageUrl);
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e) {
throw e;
} finally {
if (dis != null)
dis.close();
}
Base64Encoder encoder = new Base64Encoder();
return data != null ? encoder.encode(data) : "";
}
/**
*
* @Title: readInputStream
* @Description: 将网络图片流转换成数组
* @param @param inputStream
* @param @return
* @param @throws IOException
* @return byte[]
* @throws
*/
public static byte[] readInputStream(InputStream inputStream) throws IOException {
byte[] buffer = new byte[1024];
int len = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while((len = inputStream.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
bos.close();
return bos.toByteArray();
}
/**
* @Title: downloadImg
* @Description: 网络图片下載到本地
* @param @param imgUrl:网络图片,http开头
* @param @return 返回下载到本地的图片路径
* @param @throws Exception
* @return String
* @throws
*/
public String downloadImg(String imgUrl) throws Exception{
// 构造URL
URL url = new URL(imgUrl);
// 打开连接
URLConnection con = url.openConnection();
//设置请求超时为5s
con.setConnectTimeout(5*1000);
// 输入流
InputStream is = con.getInputStream();
// 1K的数据缓冲
byte[] bs = new byte[1024];
// 读取到的数据长度
int len;
//创建下载路径
String savePath = "D://download//";
String filename = ".jpg";
String returnUrl = savePath+filename;
File sf = new File(savePath);
if(!sf.exists()){
sf.mkdirs();
}
// 输出的文件流
OutputStream os = new FileOutputStream(sf.getPath()+"\\"+filename);
// 开始读取
while ((len = is.read(bs)) != -1) {
os.write(bs, 0, len);
}
// 完毕,关闭所有链接
os.flush();
os.close();
is.close();
return returnUrl;
}
}
最后创建一个freemaker模板存放我们需要打印的内容,打印的key要和map里面一样才行,有时候需要根路径的时候,根路径要放到map里,map里存放list和root
这是我要打印的二维码链接验证的东西,把卡券卖给用户后,用户扫码填写密码就可以来验证了,这样可以一次打印多张二维码。
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body style="text-align:left;margin-top:3%;background-color:#eee;margin-left:3%;">
<#list list as card>
<div class="tip-dialog">
<p>微信扫码验证卡券</p>
<p>提货卡号:${card.cardnumber!}</p>
<#if card.status==0>
未验证
<#else>
验证时间:${card.verifyTime!}
</#if>
<div class="erweima_box">
<img width="200px" src="${root}${card.ewm!}">
</div>
<p>提货卡密码:${card.cardpassword!}</p>
</div>
<HR align=center style="border:3 double #987cb9" width="80%" color=#987cb9 SIZE=3>
</#list>
</body>
</html>