前言:前端时间业主提出一个需求,ECharts生成的统计图表需要导出word和html并提供下载,好家伙这个给我搞的就很难受啊,关键word和html里面就一张图片,这 这 这。。。(直接截图不就好了吗,还需要下载吗?),但是也没办啊,得照做啊!来吧,展示。
/***
* 导出Word
*
* @return
* @throws Exception
*/
@RequestMapping(value = "/exportMillCertificate", method = RequestMethod.POST)
@ResponseBody
public void exportMillCertificate(HttpServletRequest request, HttpServletResponse response) throws Exception {
//前端传过来的base64图片地址,我们需要把需要的参数放到map中
Map<String, Object> map = new HashMap<String, Object>();
String base64Url = request.getParameter("base64Url");
//此处因为formdata方式传参,base64会被转义,需要把空格换成+
String s = base64Url.replaceAll(" ", "+");
//因为模板中已经指定为图片格式了,所以需要截取,不然导出的word图片不会显示(血泪史)
String substring = s.substring(22);
map.put("image", substring);
WordUtils.exportMillCertificateWord(request, response, map);
//下面这个方法是可以直接把生成的文件放到本地(为了方便自己测试用的)
/* try {
//创建配置实例
Configuration configuration = new Configuration();
//设置编码
configuration.setDefaultEncoding("UTF-8");
//ftl模板文件统一放至 com.lun.template 包下面com.admin.wordtest /yuanda-biz/src/main/java/com/zkingsoft/tools/xzcvs.ftl
configuration.setClassForTemplateLoading(WordController.class, "/template/");
//获取模板
Template template = configuration.getTemplate("wordImage.ftl");
//输出文件
File outFile = new File("E:/test.doc");
//如果输出目标文件夹不存在,则创建
if (!outFile.getParentFile().exists()) {
outFile.getParentFile().mkdirs();
}
//将模板和数据模型合并生成文件
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));
//生成文件
template.process(map, out);
//关闭流
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}*/
}
此处为工具类
package com.zhzf.util;
import com.zhzf.desk.controller.WordController;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Map;
public class WordUtils {
//配置信息,代码本身写的还是很可读的,就不过多注解了
private static Configuration configuration = null;
//这里注意的是利用WordUtils的类加载器动态获得模板文件的位置
// private static final String templateFolder = WordUtils.class.getClassLoader().getResource("").getPath();
private static final String templateFolder = "template/wordImage.ftl";
// private static final String templateFolder = WordUtils.class.getClassLoader().getResource("/template/image.ftl").getPath();
static {
configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
try {
configuration.setDirectoryForTemplateLoading(new File(templateFolder));
} catch (IOException e) {
e.printStackTrace();
}
}
private WordUtils() {
throw new AssertionError();
}
public static void exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map map) throws IOException, TemplateException {
// Template freemarkerTemplate = configuration.getTemplate("");
configuration.setClassForTemplateLoading(WordUtils.class, "/template/");
//获取模板
Template template = configuration.getTemplate("wordImage.ftl");
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
File file = null;
InputStream fin = null;
ServletOutputStream out = null;
try {
// 调用工具类的createDoc方法生成Word文档
file = createDoc(map, template);
fin = new FileInputStream(file);
response.setCharacterEncoding("utf-8");
response.setContentType("application/msword");
// 设置浏览器以下载的方式处理该文件名
String fileName = "ansysWord" + ".doc";
response.setHeader("Content-Disposition", "attachment;filename="
.concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
bis = new BufferedInputStream(new FileInputStream(file));
bos = new BufferedOutputStream(response.getOutputStream());
byte[] buff = new byte[10240];
int bytesRead;
while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
bis.close();
bos.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fin != null) fin.close();
if (out != null) out.close();
if (file != null) file.delete(); // 删除临时文件
}
}
private static File createDoc(Map<?, ?> dataMap, Template template) {
String name = "test.doc";
File f = new File(name);
Template t = template;
try {
// 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");
t.process(dataMap, w);
w.close();
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
return f;
}
}
- 此处为模板,关于模板的制作:新建空白文档,并插入一张图片,注意这个图片的大小就是你导出word中图片的大小如果不做更改的话
- 另存为word xml文件
- 更改后缀名为.ftl格式
- 打开.ftl文件把base64地址换成${image}
- 把模板存到本地项目中就行
下面是html的。
@RequestMapping(value = "/exportHtml", method = RequestMethod.POST)
@ResponseBody
public void exportHtml(HttpServletRequest request, HttpServletResponse response) throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
String base64Url = request.getParameter("base64Url");
//和转成word是一样的,还是需要替换下
String imagePath = base64Url.replaceAll(" ", "+");
//获取模板
String filePath = WordController.class.getClassLoader().getResource("/template/wordHtml.html").getPath();
String disrPath = "E:/";
String fileName = "ansysHtml";
MakeHtml(filePath, imagePath, fileName, disrPath, response);
}
/**
* @param filePath 设定模板文件
* @param imagePath 需要显示图片的路径
* // * @param disrPath 生成html的存放路径
* @param fileName html名称
*/
public static void MakeHtml(String filePath, String imagePath, String fileName, String disrPath, HttpServletResponse response) {
try {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
String templateContent = "";
// 读取模板文件
FileInputStream fileinputstream = new FileInputStream(filePath);
int lenght = fileinputstream.available();
byte bytes[] = new byte[lenght];
fileinputstream.read(bytes);
fileinputstream.close();
templateContent = new String(bytes);
System.out.print(templateContent);
templateContent = templateContent.replaceAll("###title###", "<img src=" + '"' + imagePath + '"' + "/>");
System.out.print(templateContent);
response.setContentType("application/test-html");
response.setHeader("Content-Disposition",
"attachment;filename=downloadfilename.html");
// 读取本地文件的输入流
InputStream in ;
// 输出响应正文的输出流
OutputStream out;
in = new ByteArrayInputStream(templateContent.getBytes());
// 把本地文件发送给客户端
out = response.getOutputStream();
int byteRead = 0;
byte[] buffer = new byte[512];
while ((byteRead = in.read(buffer)) != -1) {
out.write(buffer, 0, byteRead);
}
in.close();
out.flush();
out.close();
} catch (Exception e) {
System.out.print(e.toString());
}
}
下面是前端代码,我们用的是angular。
// 下载文件 downloadFile(file, fileType, suffix) { const blob = new Blob([file], { type: fileType }); const fileName = '门前五包统计'; if ('msSaveOrOpenBlob' in navigator) { // Microsoft Edge and Microsoft Internet Explorer 10-11 window.navigator.msSaveOrOpenBlob(blob, fileName + suffix); } else { const objectUrl = URL.createObjectURL(blob); const a = document.createElement('a'); document.body.appendChild(a); a.setAttribute('style', 'display:none'); a.setAttribute('href', objectUrl); a.setAttribute('download', fileName); a.click(); URL.revokeObjectURL(objectUrl); } } // 获取echart图表图片 getEchartUrl() { const url = this._echarts.getDataURL({ type: 'jpeg', pixelRatio: 1, backgroundColor: '#fff' }); return url; } // 下载 word downloadWord() { const params = { base64Url: this.getEchartUrl() }; this.dataService.exportMillCertificate(params).subscribe((result) => { this.downloadFile(result, 'application/msword', '.doc'); }); } // 下载 html downloadHtml() { const params = { base64Url: this.getEchartUrl() }; this.dataService.exportHtml(params).subscribe((result) => { this.downloadFile(result, 'text/html', '.html'); }); }
希望这篇文章对大家有用,我是文静的美男子!!!