导出包含富文本内容和图片的word和pdf

导出包含富文本内容和图片的word和pdf

这里主要提到是需要注意的几个地方,适合已经研究过使用过freemarker+xml方式导出word的伙伴们,在此基础上应该一看就明白。若看不懂请自行查找导出word的资料,资料很多,这里主要是记录下导出包含富文本内容和图片的方式,以便后续自查。

需求是需要按照特定模板导出word,其中有些功能模块的内容是使用ckeditor编辑器填写的,这就涉及到了导出时要兼容富文本所包含的html标签, 这里多说两句:有两种情况 一、导出内容不包含富文本内容和富文本中增加的图片的情况,大体使用freemarker+xml方式,制作模板步骤:用office的word(据说WPS做得模板不可用,未亲测)做导出模板–>另存为xml格式文件—>再直接改后缀名为ftl放入项目中。我是先用的freemarker+xml方式导出word,发现解析不了html,又改用的freemarker+mht方式。因为他解析不了html代码,所以导出富文本内容没有合格结构是乱的,图片也无法显示 二、导出内容包含富文本和图片,大体使用freemarker+mht方式,制作模板步骤:用office的word(据说WPS做得模板不可用,未亲测)做导出模板–>另存为mht格式文件—>再直接改后缀名为ftl放入项目中 下面我们着重介绍下第二中情况:

本人做的时候也是网上各种查资料,特此感谢两篇文章大家也可以看下 文章一 文章二 特别感谢其中一位博主,还提供了源码包,放入项目中只需要根据项目实际情况调整下图片路径和导出word方式即可。

1、做模板

首先第一步是制作模板,模板步骤见上面,制作模板时也可以不用占位符使用常量占位,到程序中知道显示位置再改成${} 占位符也是一样的。使用1111或者aaa的常量,个人感觉模板排查起来要方便些

2.处理mht文件

打开我们的mht文件并处理,我使用EditPlus查看编码,很多编辑器都可以打开看代码,需要注意的是,模板生成时有时占位符${content!’’}有可能会被word自身的标签截断,因为mht文件有时候会自动换行,会在单词中间加上= 号 或者在{ 等符号与单词之间加上一些mht文件的样式,我们都要删掉,不删掉可能会造成模板异常,

2.1在模板中找到下面截图中的代码

${imagesBase64String} 和 ${imagesXmlHrefString}这两个占位符是我们手动加进去的,简析富文本图片的核心就在这里,按照这个位置加进去即可

2.2全文检索gb2312把他改成utf-8,看到前面加上3D前缀的要保留mht文件很多地方都是以3D为标识的

2.3 在模板文件中找到Content-Location: file:///C:/B2260B68/file7736.files,并记录下来,后面代码中要用到

到这里模板文件就做完了,后缀名改为ftl放入项目中,如何取值或者list循环取值,判断等等都是freemarker规则,跟ftl一样使用

3、下面主要介绍代码中主要的几部分,详细的请下载源码包查看代码中有下图中的代码块,设置的值就是上面在模板文件中找到的,相匹配上就可以了,后三项具体为什么设这个值我也没搞明白,就这么用也没问题,因为到后面具体用到这三个值的时候是加上32位随机码组合而成的唯一标识再使用的。 下面是生成word的方法: // 配置信息,代码本身写的还是很可读的,就不过多注解了private static Configuration configuration = null;// 这里注意的是利用WordUtils的类加载器动态获得模板文件的位置// private static final String templateFolder =// WordUtils.class.getClassLoader().getResource("../../").getPath() +// "WEB-INF/templetes/";//获取系统模板所在路径private static final String templateFolder = getTempletePath("");static {configuration = new Configuration();configuration.setDefaultEncoding("utf-8");try {configuration.setDirectoryForTemplateLoading(new File(templateFolder));} catch (IOException e) {e.printStackTrace();}}//exportWord是项目中放ftl文件模板的文件夹,得到的是存放模板的路径private static String getTempletePath(String fileName) {try {File temFile = new File(Thread.currentThread().getContextClassLoader().getResource("/").toURI().getPath());String templatePath = (new StringBuilder(String.valueOf(temFile.getParentFile().getParentFile().getPath()))).append(File.separator).append("exportWord").append(File.separator).append(fileName).toString();return templatePath;} catch (URISyntaxException e) {e.printStackTrace();}return "";}//controller调用此方法public static void exportRichWord(HttpServletRequest request, HttpServletResponse response, Map map,String title, String ftlFile) throws IOException {Template freemarkerTemplate = configuration.getTemplate(ftlFile);File file = null;InputStream fin = null;ServletOutputStream out = null;try {WordHtmlGeneratorHelper.handleAllObject(map);// 调用工具类的createDoc方法生成Word文档file = createDoc(map, freemarkerTemplate);fin = new FileInputStream(file);response.setCharacterEncoding("utf-8");response.setContentType("application/msword");SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");String formatDate = sdf.format(new Date());// 设置浏览器以下载的方式处理该文件名String fileName = title + formatDate + ".doc";response.setHeader("Content-Disposition","attachment;filename=".concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));out = response.getOutputStream();byte[] buffer = new byte[512]; // 缓冲区int bytesToRead = -1;// 通过循环将读入的Word文件的内容输出到浏览器中while ((bytesToRead = fin.read(buffer)) != -1) {out.write(buffer, 0, bytesToRead);}} 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 = "sellPlan.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;}

下面是controller中调用导出方法,并往map中放值,里面的imagesBase64String就是对应的模板中的占位符,下面这段代码是模板中,富文本添加的内容要经过特殊处理,如果模板中只有一个富文本,如下图

if (handler1.getDocBase64BlockResults() != null&& handler1.getDocBase64BlockResults().size() > 0) {for (String item : handler1.getDocBase64BlockResults()) {handledBase64Block += item + " ";}}dataMap.put("imagesBase64String", handledBase64Block);if (handler1.getXmlImgRefs() != null&& handler1.getXmlImgRefs().size() > 0) {for (String item : handler1.getXmlImgRefs()) {xmlimaHref += item + " ";}}dataMap.put("imagesXmlHrefString", xmlimaHref);

如果导出的模板中有多个富文本,多张图片,则需要在处理最后把dataMap中的富文本中的图片累加起来即可正常显示,实际是叠加后再放入占位符,避免后面的把前面的冲掉:

//模板中包含多个富文本时String old_handledBase64Block = ""; if(dataMap.containsKey("imagesBase64String")){ old_handledBase64Block = (String) dataMap.get("imagesBase64String"); handledBase64Block = old_handledBase64Block + handledBase64Block; } dataMap.put("imagesBase64String", handledBase64Block); String old_xmlimaHref = ""; if(dataMap.containsKey("imagesXmlHrefString")){ old_xmlimaHref = (String) dataMap.get("imagesXmlHrefString"); xmlimaHref = old_xmlimaHref + xmlimaHref; } dataMap.put("imagesXmlHrefString", xmlimaHref);

最后再说下图片路径的问题,demo中的路径是博主自己写的demo适用路径,大神们后续放到自己项目中,改成自己相对应的路径即可显示。我直接跑demo中的示例图片显示不正常,我直接拿到我自己项目中改成我自己的就可以正常显示了。 以上内容仅供参考,也感谢之前大神的分享资料,帮助良多~~~

源码:源码我就不再自己上传一遍了,转大神的demo源码:https://pan.baidu.com/s/1bpj2mCn 来源于博文

**

导出包含富文本内容和图片的pdf文件

**比较简单,直接用ftl页面即可,但是重要的一点就是ftl模板的头部必须要加入,必须要加,否则富文本内容和图片不能政策显示。 页面取值的时候如图即可,gzjh和gzzj就是富文本内容 导出相关代码也贴出来一些仅供参考: 1、Controller中为map设置值 2、exportPdf实现

import java.io.ByteArrayOutputStream;import java.io.File;import java.io.IOException;import java.io.OutputStream;import java.io.StringWriter;import java.net.URISyntaxException;import java.net.URLEncoder;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Map;import java.util.regex.Matcher;import java.util.regex.Pattern;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.xhtmlrenderer.pdf.ITextRenderer;import com.lowagie.text.pdf.BaseFont;import freemarker.template.Configuration;import freemarker.template.Template;public class PDFTemplateUtil {private static Configuration configuration = null;//获取系统模板所在路径private static final String templateFolder = getTempletePath("");static {configuration = new Configuration();configuration.setDefaultEncoding("utf-8");try {configuration.setDirectoryForTemplateLoading(new File(templateFolder));} catch (IOException e) {e.printStackTrace();}}/** * 通过模板导出pdf文件 * @param data 数据 * @param templateFileName 模板文件名 * @throws Exception */ public static ByteArrayOutputStream createPDF(Map data, Template template) throws Exception { ITextRenderer renderer = new ITextRenderer(); OutputStream out = new ByteArrayOutputStream(); try { // 设置 css中 的字体样式(暂时仅支持宋体和黑体) 必须,不然中文不显示 renderer.getFontResolver().addFont(templateFolder+"fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); Template t = template; StringWriter writer = new StringWriter(); // 将数据输出到html中 t.process(data, writer); writer.flush(); String html = writer.toString(); // 把html代码传入渲染器中 renderer.setDocumentFromString(html); // 设置模板中的图片路径 (这里的images在resources目录下) 模板中img标签src路径需要相对路径加图片名 如 // String url = PDFTemplateUtil.class.getClassLoader().getResource("images").toURI().toString(); // renderer.getSharedContext().setBaseURL(url); renderer.layout(); renderer.createPDF(out, false); renderer.finishPDF(); out.flush(); return (ByteArrayOutputStream)out; } finally { if(out != null){ out.close(); } } } public static void exportPdf(HttpServletRequest request, HttpServletResponse response, Map mapData,String title, String ftlFile) throws Exception{ Template freemarkerTemplate = configuration.getTemplate(ftlFile);ByteArrayOutputStream baos = null;OutputStream out = null;try {baos = createPDF(mapData, freemarkerTemplate);;// 设置响应消息头,告诉浏览器当前响应是一个下载文件response.setContentType( "application/x-msdownload");// 告诉浏览器,当前响应数据要求用户干预保存到文件中,以及文件名是什么 如果文件名有中文,必须URL编码 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");String formatDate = sdf.format(new Date());// 设置浏览器以下载的方式处理该文件名String fileName = title + formatDate + ".pdf";response.setHeader("Content-Disposition","attachment;filename=".concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));out = response.getOutputStream();baos.writeTo(out);baos.close();} catch (Exception e) {e.printStackTrace(); throw new Exception("导出失败:" + e.getMessage());} finally{if(baos != null){baos.close();}if(out != null){out.close();}}} private static String getTempletePath(String fileName) {try {File temFile = new File(Thread.currentThread().getContextClassLoader().getResource("/").toURI().getPath());String templatePath = (new StringBuilder(String.valueOf(temFile.getParentFile().getParentFile().getPath()))).append(File.separator).append("exword").append(File.separator).append(fileName).toString();return templatePath;} catch (URISyntaxException e) {e.printStackTrace();}return "";}}

比丘资源网 » 导出包含富文本内容和图片的word和pdf

发表回复

提供最优质的资源集合

立即查看 了解详情