基于Freemarker实现网页文档编辑并导出(SpringBoot)

前端时间需要实现一个能设计固定文档的格式的系统,系统目的是想实现一个类似于在线office的功能,但是要预设文档格式。

开始的第一步就是先确定要怎么样才可以导出.doc文档,根据我的了解大概有以下几种方式:

  1. jQuery-Word-Export插件可以将目标网页区域导出成文档,可以保留表格和一些简单的css样式,这个方式是我一开始选择的。因为直接导出网页内容的话,那就只需要考虑添加前端网页的功能和样式,能有更好的用户体验。但是这个插件生成的文档有个很大的问题在于没办法生成文档标题,我查阅了很多博客和网页还是没有找到解决的方法,但是这个要求是又是系统必须的,没办法只好放弃这种方式了。
  2. WebOffice控件,这个插件应该是能够实现网页在线编辑word要求的,但是这个插件我从一开始就没打算用,也没怎么去了解,主要还是感觉和系统的目的有点出入,而且要是用这个插件的话总感觉有点偷懒的感觉,但是挺好用也说不定。
  3. 通过VB来生成文档。这个是我在实习的时候,公司里有用这种方法来生成excel表格,我想应该也能够生成word文档,但是我对VB的语法实在是不熟悉,时间又比较赶没办法只能放弃了。
  4. 通过Freemarker来生成文档,这个也是我最终采用的方法。这种方法能够预设文档格式,刚刚好满足系统的要求,但其实这种方法也不能完全符合我一开始的设想,具体原因我会在接下来的内容里说明。

项目结构

因为Deadline在即,这个项目结构的层次说实话我自己也觉得有点乱七八糟。。。

  

大概总结一下在这个项目中的几个功能,代码和演示页面我会在结尾贴出来。

·生成文档

     用Freemarker输出文档的话首先需要先准备一个.ftl的模板文件。首先先打开word,将文字的样式先设置好,然后需要接收参数的地方用${参数名}来替换,就像下图这样:

     然后把这个文档保存为.xml格式,用文本编辑器打开,要确保${参数名}不能被隔开,否则参数内容没办法正常替换。然后如果要插入图片的话可以在插入位置预先随便放一张图片,然后在xml中把<pkg:binaryData></pkg:binaryData>这个里面的那些字符删除,替换成${图片名},就大概这样像图里的这样:     这里其实有个问题就是只能在指定位置插入图片,这个真的很影响文档的灵活性。我仍然没有找到一个比较好的解决方案来实现灵活的在文档内随意插入图片,想要更换图片或者文字位置,就只能够重新修改模板文件。有个想法就是让用户自己来设置模板,这样可以满足用户的个性化需求。这个方法需要足够了解word.xml的语法标签,能够解析网页模板,生成对应的word.xml格式文件。感觉这个方法有点呆,但我也没想到什么更好的方法来解决这个问题,而受限于时间,这个由用户自己生成模板的功能我还没有去完成,也仅仅是一个想法而已。。。

   将改好的.xml文件后缀名改成.ftl放在项目路径下,我是在resources里面新建了一个template1来放这个模板文件。写一个用于导出的工具类ExportUtil。

package com.homewin.util;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Map;

import freemarker.template.Configuration;
import freemarker.template.Template;
import sun.misc.BASE64Encoder;

public class ExportUtil {
	 private  Configuration configuration;
	    private  String encoding;
	    
	    public ExportUtil(String encoding) {
	    	this.encoding= encoding;
	        configuration = new Configuration(Configuration.VERSION_2_3_22);
	        configuration.setDefaultEncoding(encoding);
	        
	        configuration.setClassForTemplateLoading(this.getClass(), "/template1");
	    }
	    //载入模板文件
	    public  Template getTemplate(String name) throws Exception {
	        return configuration.getTemplate(name);
	    }
	    //将图片转化成BASE64编码类型
	    public  String getImageStr(InputStream is) throws IOException {
	        BASE64Encoder encoder = new BASE64Encoder();
	        byte[] data = new byte[is.available()];
	        is.read(data);
	        
	        is.close();
	        return encoder.encode(data);
	    }

	    //生成文档
	    public  void   exportDoc(String doc, String name,Map<String, Object> dataMap) throws Exception {
	        Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(doc), encoding));
	        getTemplate(name).process(dataMap, writer);
	        writer.flush();
	        writer.close();
	    }
	    
	
}

       要调用的话就可以这样写

		ExportUtil exportUtil = new ExportUtil("UTF-8");
		File image1 = new File("D:/test/cover.jpg");
		Map<String, Object> dataMap = new HashMap<>();
		dataMap.put("title","你想要插入的标题");
		try {
			dataMap.put("image1", exportUtil.getImageStr(new FileInputStream(image1)));
		} catch (IOException e) {
			e.printStackTrace();
		}
		String path = "D:/test/";
		exportUtil.exportDoc(path + word_name + ".doc", "templatez.ftl", dataMap);

       就能够在对应路径下创建出新的文档,要注意的是,同名文档的话会直接覆盖原文档。还有就是如果传入的字符串内有换行符的情况下,想要文档内容也换行的话可以这样写。

//这个a1_1是一个带换行符的字符串
dataMap.put("a1_1", a1_1.replaceAll("\r\n", "</w:t></w:r></w:p><w:p><w:r><w:t>"));

        还有就是网页想要预览上传图片的话可以这样写

 <input id="file" name="e_r" class="filepath" onchange="changepic(this)" type="file" style="opacity: 0;"><br>
   	<label class="pic " for="file" id="show1">
<script>
    function changepic() {
        var reads= new FileReader();
        f=document.getElementById('file').files[0];
        reads.readAsDataURL(f);
        reads.onload=function (e) {
            $("#show1").css("background-image","url("+this.result+")")
	        };
    }
</script>

这样上传图片可以在label这个标签里显示,效果大概是这样。

 

上传之后:

·短信验证码

因为之前有写过一个邮箱验证的demo,这次就试一下短信验证码,这种短信发送平台其实很多,也不太知道差别在哪里,就选了一个注册送180条短信的平台——云之讯全能力通讯开发平台。不知道现在还有没有这个活动,建议如果是自己玩的话可以选个优惠一些的平台。各个平台会提供对应的api和demo等等,上手也很简单。

项目代码我放在了github上:https://github.com/homewin21/ExportWord,只需要改一下数据库用户名密码就可以正常使用,数据库表字段和entity内的User类和Word类的属性映射一致。如果也是云之讯平台的话,修改config.properties内的属性,要是其他短信平台的话可以重写一下MailUtil这个类,然后在调用验证码的地方改一下就可以了。

运行页面我放在了服务器上,有的改动还没有同步上去,效果其实是差不多就这样了。

总结

很久都没有写博客了,在写项目的时候有遇到不少问题,看了不少前人写的博客,都给了我很多帮助和启发。说实话现在这个水平还没办法写出那种技术性强,结构整洁清楚的博客,但是我希望以后如果接触比较有意思的东西或者学到一些新知识都能够有时间写一个博客总结一下。虽然说实话整个文章都很抽象,还是留着吧,希望以后自己能看到这篇博客!

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值