文档章节

java生成word(文字和图片)

RampageAngle
 RampageAngle
发布于 2016/07/15 12:02
字数 1024
阅读 75
收藏 0

1、整体思路
    利用xml模板,在模板中预留占位标识(${yourContent}),然后将xml转为ftl文件,通过Map<String, Object>传值填充对应的内容即可,word其实和html一样,也有自己的xml标签,表头、段落、图片、以及字体、标题等的标签。文字必须包含在段落中,如:<w:p><w:r><w:t>${yourContent}</w:t></w:r></w:p>,图片必须是在
<w:pict><w:binData>${image}<w:binData><v:shape><v:imagedata</v:shape>
其中<w:binData>、<v:shape>和<v:imagedata>有几个必填参数,后面的代码会涉及到。集合的循环遍历通过<#list yourListName as alias>${alias.property}...</#list>方式实现。
2、生成模板
    新建word模板,设置自己要替换的内容。比如下面例子:
        我的文档
        作者:author 时间:time 内容:content
        把新建好的word导出成word2003xml文件,然后将author改成${author},time改成${time},content改成${content}然后修改后缀名为ftl文件,存到项目里面。
3、替换内容
    实际操作中,不光会遇到纯文字的,经常会遇到文字加图片。图片的实现:先转换成base64的字符串,然后填充到图片的标签中(网络图片,必须先下载到本地才能转换)。下面是转换的代码:
----------

/**
     * 替换内容中的图片,样式
     * 
     * @param content
     * @return
     * @throws Exception
     */
    public String replaceImage(String content) throws Exception {
        try {
            Pattern p = Pattern.compile("<img[^>]+src\\s*=\\s*['\"]([^'\"]+)['\"][^>]*>");
            Matcher m = p.matcher(content);
            int i = 0;
            content = StyleFilter.shieldStyle(content);
            while (m.find()) {
                String width = getWidth(m.group());
                String height = getHeight(m.group());
                String target = getWholeImage(m.group(1), width, height);

                content = content.replace(m.group(), target);
            }
        } catch (ConfigurationException e) {
            e.printStackTrace();
        }
        return content;
    }
    
    public String getWidth(String content) {
        String regex = "width=['\"]?(.*?)['\"]?\\s.*?>";

        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(content);
        while (m.find()) {
            return m.group(1);
        }
        return null;
    }

    public String getHeight(String content) {
        String regex = "height=['\"]?(.*?)['\"]?\\s.*?>";

        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(content);
        while (m.find()) {
            return m.group(1);
        }
        return null;
    }
    
    /**
     * 生成图片(独立成段落的图片,仅前半部分,后半部分手动拼接)
     * 
     * @param imgUrl
     * @param width
     * @param height
     * @return
     * @throws Exception
     */
    public String getWholeImage(String imgUrl, String width, String height) throws Exception {
        String result = "";
        try {
            if (null != width && null != height) {
                String no = Math.random() * 100 + "";
                String binData1 = "<w:pict><w:binData w:name=\"wordml://" + no + ".png\" xml:space=\"preserve\">";
                String binData2 = "</w:binData><v:shape id=\"" + no + "\" type=\"#_x0000_t75\" style=\"width:" + width
                        + ";height:" + height + "\"><v:imagedata src=\"wordml://" + no + ".png\"/></v:shape>";
                result = binData1 + getImageStr(imgUrl) + binData2 + "</w:pict>";
            } else {
                String no = Math.random() * 100 + "";
                String binData1 = "<w:pict><w:binData w:name=\"wordml://" + no + ".png\" xml:space=\"preserve\">";
                String binData2 = "</w:binData><v:shape id=\"" + no
                        + "\" type=\"#_x0000_t75\"><v:imagedata src=\"wordml://" + no + ".png\"/></v:shape>";
                result = binData1 + getImageStr(imgUrl) + binData2 + "</w:pict>";
            }
        } catch (ConfigurationException e) {
            e.printStackTrace();
        }
        return result;
    }
其中这两块的名字必须是一致的![](leanote://file/getImage?fileId=57885a94128c7b03ba000000)
/**
     * 图片转码
     * 
     * @return 返回图片base64字符串
     * @throws Exception
     */
    public static String getImageStr(String imgUrl) throws Exception {
        String imgPath = download(imgUrl, Math.random() * 100 + ".png", Config.ReadStringPropertie("pictureDownload"));
        InputStream in = null;
        byte[] data = null;
        try {
            in = new FileInputStream(imgPath);
            
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);
    }

/**
     * 下载图片的方法(图片下载到本地后才可转化成base64字符串)
     * 
     * @param urlString
     * @param fileName
     * @param savePath
     * @return
     * @throws Exception
     */
    public static String download(String urlString, String fileName, String savePath) throws Exception {
        // 构造URL
        URL url = new URL(urlString);
        // 打开连接
        URLConnection con = url.openConnection();
        // 设置请求超时为5s
        con.setConnectTimeout(5 * 1000);
        // 输入流
        InputStream is = con.getInputStream();

        // 1K的数据缓冲
        byte[] bs = new byte[1024];
        // 读取到的数据长度
        int len;
        // 输出的文件流
        File sf = new File(savePath);
        if (!sf.exists()) {
            sf.mkdirs();
        }
        String imgUrl = sf.getPath() + "\\" + fileName;
        OutputStream os = new FileOutputStream(sf.getPath() + "\\" + fileName);
        // 开始读取
        while ((len = is.read(bs)) != -1) {
            os.write(bs, 0, len);
        }
        // 完毕,关闭所有链接
        os.close();
        is.close();
        return imgUrl;
    }
    
    enter code here
    调用replaceImage方法获取处理过的字符串,然后赋值到Map中,再调用创建word的方法:
    public String createWord(Map<String, Object> dataMap) {
        String path = "/myWrongBook" + Math.random() * 3 + ".doc";
        try {
            Template t = null;
            configuration.setClassForTemplateLoading(this.getClass(), "your template path"); // FTL文件所存在的位置

            t = configuration.getTemplate("template.ftl");

            File outFile = new File(Config.ReadStringPropertie("wrongBooks") + path);
            Writer out = null;
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));

            t.process(dataMap, out);
            out.close();
            path = Config.ReadStringPropertie("serverPath") + "/wrongBooks" + path;
            //Config.ReadStringPropertie("serverPath")是获取服务器路径的方法,就不给出了
        } catch (IOException ie) {
            ie.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return path;
    }
----------
path就是最终生成的word下载地址,不过这样的地址会比较长,给用户体验不是很爽,可以利用新浪云计算短网址转换成短链接http://jump.sinaapp.com/
    enter code here
    

© 著作权归作者所有

共有 人打赏支持
RampageAngle
粉丝 2
博文 4
码字总数 3380
作品 0
兰州
程序员
私信 提问
Apache POI 操作Word部分

Apache POI ----Word部分 最近在研究Apache POI,不过只研究了如何做word的部分。网上对于Excel等的介绍也很多例子也很多,但是对于word缺少的可怜,导致我学的也很费劲,只能算是会了皮毛。...

QH_C
2014/11/15
0
0
使用 Grapicmagick 和 Im4java 处理图片

ImageMagick是个图片处理工具可以安装在绝大多数的平台上使用,Linux、Mac、Windows都没有问题。GraphicsMagick是在ImageMagick基础上的另一个项目,大大提高了图片处理的性能,在linux平台上...

voole
05/07
0
0
聊聊并发(二)Java SE1.6中的Synchronized

在多线程并发编程中Synchronized一直是元老级角色,很多人都会称呼它为重量级锁,但是随着Java SE1.6对Synchronized进行了各种优化之后,有些情况下它并不那么重了,本文详细介绍了Java SE1....

陶邦仁
2015/03/18
0
0
PageOffice,word常用接口对象--Shape类

Shape类用来读取Word中的图形、图片,一个Shape对象代表Word中的一个图片。 Shape类所属命名空间 Java开发时命名空间为:com.zhuozhengsoft.pageoffice.wordreader ASP.NET开发时命名空间为:...

山里的红杏
09/10
0
0
深入学习Tesseract-ocr识别中文并训练字库的方法

  上篇文章简单的学习了tesseract-ocr识别图片中的英文(链接地址如下:https://www.cnblogs.com/wj-1314/p/9428909.html),看起来效果还不错,所以这篇文章继续深入学习tesseract-ocr识别...

战争热诚
08/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

阿里千万级高性能、高并发架构的经验之谈

架构以及我理解中架构的本质 在开始谈我对架构本质的理解之前,先谈谈对今天技术沙龙主题的个人见解,千万级规模的网站感觉数量级是非常大的,对这个数量级我们战略上 要重 视 它 , 战术上又...

别打我会飞
20分钟前
3
0
Adnroid架构的详细说明

armeabi armeabi是一个非常老的基于ARM的架构。从Android 4.4开始,CDD(compatibility definition)严格要求ARMv7读取CDD文档。 CDD是Google向设备制造商提供的每个Android版本的规范,它包...

CrazyManDF
22分钟前
3
0
微信小程序内嵌网页web-view

web-view 组件是一个可以用来承载网页的容器,会自动铺满整个小程序页面。个人类型与海外类型的小程序暂不支持使用。 客户端 6.7.2 版本开始,navigationStyle: custom 对 <web-view> 组件无...

xiaogg
23分钟前
2
0
单例模式

第一种方式 public class SingletonA { public static final SingletonA INSTANCE = new SingletonA(); private SingletonA(){ //do something }} 第二种方式 public......

wuyiyi
24分钟前
2
0
git: Authentication failed for错误解决

如果push遇到在输入密码是输错后,就会报这个错误fatal: Authentication failed for 解决办法: git config --system --unset credential.helper 之后你在push就会提示输入名称和密码...

落雪飞声
25分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部