精华内容
下载资源
问答
  • 就是,word文档,写完了,保存 没有任何错误提示,保存关闭后,文档大小变成了0字节,里边的东西都没有了 这种情况可以恢复吗 重新打开这个文档,也没有任何提示恢复的信息 在最近使用的目录里也没有缓存文件之类的,想...
  • 字节流生成word文档

    2019-05-04 02:05:14
    NULL 博文链接:https://yuhuiblog695685688425687986842568269.iteye.com/blog/2433333
  • 前些天需求要完成导出word文档功能,基础数据导出word文档,网上也能搜到很多源代码,但是我这边要求是服务器上的图片(只给出服务器图片路径,从服务器得到图片),前前后后加起来就不好内容了,网上并没有找到处理这种的...

    Springboot 项目freemarker导出word文档(文档内容包括数据以及服务器图片)

    前些天有需求要完成导出word文档功能,基础数据导出word文档,网上也能搜到很多源代码,但是我这边要求是服务器上的图片(只给出服务器图片路径,从服务器得到图片),前前后后加起来就不好内容了,网上并没有找到处理这种的代码和解决方式,只好自己写了,弄完了来记录下,防止以后再用.

    首先动手之前整理下思路:

    第一: 分析下word文档内容: 数据 + 图片
    1. 数据 ——— 数据库获取
    2. 图片 ——— 拿到数据库连接地址,获取服务器图片.(重点)
    第二:分析下实现思路
    1. 数据部分很好处理,后面代码上直接可以一步完成
    2. 图片部分需要注意一下
           2.1.获取数据库图片链接(这个简单跟数据一样处理)
           2.2.根据链接从服务器获取图片并保存到本地
               2.2.1.注意:数据库得到的图片链接,要想从服务器获取,有的字符是需要转义的,这个需要操作的
           2.3.读取本地的图片,将图片信息转为base64,存入跟普通数据一起的实体类中
           2.4.将这个实体类导出到指定的word模板中
    

    上述仅仅为简单分析,实际的编写过程中肯定会遇到很多需要额外操作的内容,后面为大家分析.
    那么现在就开始编写代码吧:

    我们用到的技术为freemarker,其实有好多导出文档的技术,这边就不多说了.
    第一步:添加pom.xml 我们所需要的依赖,这边我就把我差不多要用的拿出来了,代码太多了就不全粘了.
    当然重点就是freemarker.

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.16.16</version>
                <scope>provided</scope>
            </dependency>
    
            <!-- JSONObject对象依赖的jar包 -->
            <dependency>
                <groupId>commons-beanutils</groupId>
                <artifactId>commons-beanutils</artifactId>
                <version>1.9.3</version>
            </dependency>
            <dependency>
                <groupId>commons-collections</groupId>
                <artifactId>commons-collections</artifactId>
                <version>3.2.1</version>
            </dependency>
            <dependency>
                <groupId>commons-lang</groupId>
                <artifactId>commons-lang</artifactId>
                <version>2.6</version>
            </dependency>
            <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>1.1.1</version>
            </dependency>
            <dependency>
                <groupId>net.sf.ezmorph</groupId>
                <artifactId>ezmorph</artifactId>
                <version>1.0.6</version>
            </dependency>
            <dependency>
                <groupId>net.sf.json-lib</groupId>
                <artifactId>json-lib</artifactId>
                <version>2.2.3</version>
                <classifier>jdk15</classifier><!-- 指定jdk版本 -->
            </dependency>
            <!-- Json依赖架包下载 -->
    
            <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
            <dependency>
                <groupId>com.google.code.gson</groupId>
                <artifactId>gson</artifactId>
                <version>2.8.5</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>4.5</version>
            </dependency>
            <!--mybatis-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.47</version>
            </dependency>
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-support</artifactId>
                <version>2.1.9</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
            <groupId>org.freemarker</groupId>
                <artifactId>freemarker</artifactId>
                <version>2.3.23</version>
             </dependency>
        </dependencies>

    首先我们需要数据,也就是从数据库里面获取到的数据,这个我就不写了,就是简单的从数据库获取数据而已,数据的格式为List< Map< String,Object>> resList 集合.

    现在就相当于我们已经有数据了,它就是resList,里面有很多字段信息,包括图片的链接(我这边就先给出两个图片字段 jjyp,yjtp链接吧),http://192.168.0.101:1110/GPRS/Ⅰ临无40 (1).jpg ,http://192.168.0.101:1110/GPRS/Ⅰ临无40 (2).jpg (虚拟链接).

    拿到了图片的链接地址,我们就要从服务器获取图片了,并且将它保存到本地 .但是呢再次之前我们还要做的就是图片链接转码,可以直接访问图片链接,地址栏上面的链接就是转码之后的链接(浏览器自动转码),但是代码里面并不会自动转的,所以这里我们要手动转下码才行:

    public class CnToEncode {
        /**
         * @author 一只会飞的猪
         * 将字符串中的中文进行编码
         * @param s
         * @return 返回字符串中汉字编码后的字符串
         */
        public String charToEncode(String s) throws UnsupportedEncodingException {
            char[] ch = s.toCharArray();
                    String result = "";
            for(int i=0;i<ch.length;i++){
                char temp = ch[i];
                if(isChinese(temp)){
                    try {
                        // 遇到中文给中文转码
                        String encode = URLEncoder.encode(String.valueOf(temp), "utf-8");
                        result = result + encode;
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                }else{
                    // 判断是不是空格,是空格时转为 %20
                    if(temp==' '){
                        result = result + "%20";
                    }else{
                        // 判断字符是否为全角字符
                        if((int)temp>255){
                            String encode = URLEncoder.encode(String.valueOf(temp), "utf-8");
                            result = result + encode;
                        }else {
                            result = result + temp;
                        }
                    }
                }
            }
            return result;
        }
        /**
         * 判断字符是否为汉字
         * @param c
         * @return
         */
        private  boolean isChinese(char c) {
            Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
            if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                    || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
                    || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
                    || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) {
                return true;
            }
            return false;
        }
        }

    上面是我写好的方法,可以直接拿来用的.转码之后,你的图片链接就可以在代码里面访问服务器图片了,下面就来写访问服务器图片并返回图片输入流:

      public static InputStream getUrlImages(String imagesurl) throws UnsupportedEncodingException {
                 InputStream inputStream = null;
                 HttpURLConnection httpURLConnection = null;
                 try {
                     URL url = new URL(imagesurl);
                     if (url != null) {
                         httpURLConnection = (HttpURLConnection) url.openConnection();
                         httpURLConnection.setConnectTimeout(9000);
                         httpURLConnection.setRequestMethod("GET");
                         int responseCode = httpURLConnection.getResponseCode();
                         if (responseCode == 200) {
                             inputStream = httpURLConnection.getInputStream();
                         }
                     }
                 } catch (Exception e) {
                     e.printStackTrace();
                 }
                 return inputStream;
             }

    然后保存到本地:

     // 将服务器图片保存到本地  输入流---->转为输出流写到文件中
               public void  ImageSaveLocal(String imagepath,String imagename,String imageurl) throws UnsupportedEncodingException {
                   CnToEncode cntoencode = new CnToEncode();
                   String imagesurl=cntoencode.charToEncode(imageurl);
                   int len = 0;
                   FileOutputStream fileOutputStream = null;
                   InputStream inputStream = getUrlImages(imagesurl);      // 得到服务器图片的输入流
                   // 创建文件夹
                   File file = new File(imagepath);
                   if (file.exists()) {
                       if (!file.isDirectory()) {
                           file.mkdir();
                       }
                   } else {
                       file.mkdir();
                   }
                   try {
                       byte[] imagesize = new byte[inputStream.available()];    // 图片长度缓存数组
                       fileOutputStream = new FileOutputStream(imagepath + "/" + imagename);   // 将要写入的图片地址
                       while ((len = inputStream.read(imagesize)) != -1) {
                           fileOutputStream.write(imagesize, 0, len);          // 写入图片
                       }
                   } catch (IOException e) {
                       e.printStackTrace();
                   } finally {
                       try {
                           // 关闭流
                           fileOutputStream.close();
                           inputStream.close();
                       } catch (IOException e) {
                           e.printStackTrace();
                       }
                   }
               }

    我这边对文件夹的做了一个分类,有需要的可以看下,是按照图片链接的类别分的,比如gps是一类.
    这里写图片描述

    既然图片已经保存到了本地了,那么接下来就要读取本地的图片信息了.

      // 图片数据转Base64字节码 字符串
      // imgFile是上面存到本地的图片路径
              public String getImageStr(String imgFile){
                  InputStream in=null;
                  byte[] data=null;
                  try {
                      in=new FileInputStream(imgFile);
                      data=new byte[in.available()];
                      in.read(data);
                      in.close();
                  } catch (FileNotFoundException e) {
                      e.printStackTrace();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
                  BASE64Encoder encoder=new BASE64Encoder();
                  return encoder.encode(data);
              }
    整理下思路我们做了什么.
         上面的各种方法让我们能够将服务器上面的图片存到本地,然后得到图片的base64字节码,图片的base64字节码是可以到处 
      word的也是能够显示的,咦~那我们是不是就可以到处了呢?nonono 现在还差一步,那就是把普通的数据和你处理之后的 图片 
      base64数据重新封装到一个Map集合中,这样一来,原数据集合中的图片数据就是我们所需要的base64字节码了啊,这样就能
      完整的导出啦.
    

    那现在我们在整个用来封装的方法:

    // 参数介绍:jsondata 这个参数是json字符串是你的图片字段名,没有这个系统是不会知道你哪些字段是图片的.
    //         map: 这个当然就是我们的数据了,包括了图片字段数据哦,后面给它替换了就行了
               starturl: 这个是服务器图片前缀,这你们根据需要而定
               imagespath:图片临时保存地址,也就是我门本地的图片地址了
      public Map<String,Object> JsonToMap(String jsondata,Map<String,Object> map,String starturl,String imagepath) throws UnsupportedEncodingException {
                   // starturl="http://101.37.20.41:9004/";
                    Map<String,Object> resmap = new HashMap<>();
                 // 解析json字符串
                    JSONObject jsonObject = JSONObject.fromObject(jsondata);
                    resmap = jsonObject;    // 将图片字段名转为map,后面好使用
                    // 实现源数据的图片数据被base64字节码替换
                    for ( String key : resmap.keySet()) {
                        if ("".equals(map.get(key)) || map.get(key) == null) {
                            String image = getImageStr(imagepath + "/" + "空白.jpg");
                            map.put(key,image);
                        } else {
                            String imageurl = starturl + map.get(key);
                            String imagename = (String) map.get(key);
                            String filetype = imagename.substring(0, imagename.indexOf("/"));   // 截取字段值"/" 之前的字符串作为二级文件夹
                            // 创建本地的二级文件夹
                            File file = new File(imagepath + "/" + filetype);
                            if (file.exists()) {
                                if (!file.isDirectory()) {
                                    file.mkdir();
                                }
                            } else {
                                file.mkdir();
                            }
                            // 拉取服务器图片存入本地
                            ImageSaveLocal(imagepath, imagename, imageurl);
                            // 图片转码
                            String image = getImageStr(imagepath + "/" + imagename);
                            map.put(key, image);
                        }
                    }
                         return map;
                }

    这样以来我们就得到了完美的数据结果了map.

    各位观众!接下来就开始导出word文档了.开始之前我们要制作一个xml文档模板,这个至于怎么做网上有好多教程,当然坑也多.
    那我们就上代码了:

    package com.jshhxx.commontoolsservice.controller;
    import com.jshhxx.commontoolsservice.common.AbstractController;
    import com.jshhxx.commontoolsservice.common.FileToZip;
    import com.jshhxx.commontoolsservice.common.ImagesFileCommon;
    import com.jshhxx.commontoolsservice.common.MapKeyToLowercase;
    import com.jshhxx.commontoolsservice.service.ExportWord.ExportWordService;
    import org.apache.ibatis.annotations.Param;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.*;
    
    import java.io.*;
    import java.util.*;
    
    import static com.jshhxx.commontoolsservice.common.FileToZip.fileToZip;
    
    @RestController
    public class ExportController extends AbstractController {
    
    /**
     * @Autor  一只会飞猪
     * @dis    信息导出word文档
     * @param  wordType  给文档分类 gps/fcb 等
     * @param  reslut    数据
     * @param  wordPath  导出路径
     * @param  wordname  导出名称(单条数据导出命名有效,多条数据导出zip无效)
     * @param  wordfieldname  批量导出名称字段
     * @param  templatename    模板名称
     * @Param  jsondata  图片字段json
     *
     * */
        @Autowired
        private ExportWordService exportWordService;
    
        private static Logger log = LoggerFactory.getLogger(ExportController.class);
    
        @Value("${ToWordPath}")
        private  String ToWordPath;
    
        @Value("${ImagePath}")
        private  String ImagePath;
    
        @PostMapping("/genWord")
        public Map<String,String> genWord(Model model, @RequestBody List<Map<String,Object>> resListone,
                                           @Param("wordType") String wordType,
                                           @Param("wordname") String wordname,
                                           @Param("wordfieldname") String wordfieldname,
                                           @Param("templatename") String templatename,
                                           @Param("jsondata") String jsondata,
                                           @Param("starturl") String starturl
                                            ) throws UnsupportedEncodingException {
            boolean ret = false;
            String msg = null;
            boolean flag=false;
            FileToZip fileToZip = new FileToZip();
            Map<String,String> result=new HashMap<>();
            Map<String,Object>  resMap = new HashMap<>();
            List<Map<String,Object>> resList = new ArrayList<>();
            MapKeyToLowercase mapKeyToLowercase = new MapKeyToLowercase();
            ImagesFileCommon imagesFileCommon = new ImagesFileCommon();
    
            String outputFilePath = ToWordPath;  // 获取程序的当前路径  C:/wordgenerator
            // 创建导出word文档路径  filepath1:文件基础目录路径 C:\wordgenerator,
            //                       filepath2:文件分类路径  C:\wordgenerator\gps
            //                       filepath3:文件最终导出路径 C:\wordgenerator\gps\gps15341394803391208
                String num = String.valueOf((int)(Math.random()*9000+1000));
                String filepath1=outputFilePath;
                String filepath2=filepath1+"/"+wordType;
                String zzfile="/"+wordType+System.currentTimeMillis();
                String filepath3=filepath2+zzfile+num;
            // 创建文件夹
                String wordPath=createfile(filepath1,filepath2,filepath3);
                String resultPath = "/"+wordType+zzfile;
    
            //将map中的key全转为小写,以便模板注入.JsonToMap() 图片数据处理
             for(int j=0;j<resListone.size();j++){
                 resMap=mapKeyToLowercase.transformUpperCase(imagesFileCommon.JsonToMap(jsondata,resListone.get(j),starturl,ImagePath));
                 resList.add(resMap);
             }
    
            // 指定目录下的新建文件夹,针对每次操作都给以唯一的文件夹存放文件
            try {
            // 导出word文档
                if (!resList.isEmpty()) {
                    if(resList.size()==1){
                        Writer out = null;
                        if("".equals(wordname)||wordname==null){
                            wordname = "新建word文档";
                            out = new OutputStreamWriter(new FileOutputStream(wordPath+"/"+wordname+".doc"), "UTF-8");
                            exportWordService.createWord("/",templatename+".xml", resList.get(0), out);
                            result.put("url",resultPath +"/"+ wordname + ".doc");
                        }else{
                            out = new OutputStreamWriter(new FileOutputStream(wordPath+"/"+wordname+".doc"), "UTF-8");
                            exportWordService.createWord("/",templatename+".xml", resList.get(0), out);
                            result.put("url",resultPath +"/"+ wordname + ".doc");
                        }
                        out.close();
                    }else {
                        for (int i = 0; i < resList.size(); i++) {
                            Writer out = null;
                            // 如果有绑定的数据字段则以数据库数据为文件名
                            wordname= (String) resList.get(i).get(wordfieldname);
                            if("".equals(wordname)||wordname==null){
                                wordname = "新建word文档"+(i+1);
                            }
                            try {
                                out = new OutputStreamWriter(new FileOutputStream(wordPath + "/"+wordname + ".doc"), "UTF-8");
                                exportWordService.createWord("/", templatename + ".xml", resList.get(i), out);
                                out.close();
                            } catch (UnsupportedEncodingException
                                    | FileNotFoundException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
    
                        // 打成压缩包
                        // 判断是是否有指定的分类别
                        if(wordType==null||"".equals(wordType)){
                              wordname= String.valueOf(System.currentTimeMillis())+num;
                              flag = fileToZip(ToWordPath, ToWordPath,wordname);
                              result.put("url", "/"+wordname+".zip");
                        }else {
                              wordname= wordType+"_"+String.valueOf(System.currentTimeMillis())+num;
                              flag = fileToZip(wordPath, wordPath,wordname);
                              result.put("url",resultPath +"/"+ wordname + ".zip");
                        }
                        if(flag){
                            log.error("===========================文件打包成功===========================");
                        }else{
                            log.error("===========================文件打包失败===========================");
                        }
                    }
                }
            } catch (Exception e) {
                msg = e.getMessage();
            }
            if((!"".equals(result))||result!=null){
                ret = true;
            }
            return result;
        }
    
        // 创建文件夹存放导出的word文件
        //  filepath1:文件基础目录路径 C:\wordgenerator,
        //  filepath2:文件分类路径     C:\wordgenerator\gps
        //  filepath3:文件最终导出路径 C:\wordgenerator\gps\gps15341394803391208
        public static  String createfile(String filepath1,String filepath2,String filepath3){
            File file1 = new File(filepath1);
            File file2 = new File(filepath2);
            File file3 = new File(filepath3);
    
            System.out.println(filepath3);
            try {
                if (file1.exists()) {
                    if (!file1.isDirectory()) {
                        file1.mkdir();
                        file2.mkdirs();
                        file3.mkdirs();
                    } else {
                        if (!file2.exists()) {
                            if (!file2.isDirectory()) {
                                file2.mkdirs();
                                file3.mkdirs();
                            } else {
                                if (!file3.exists()) {
                                    file3.mkdirs();
                                } else {
                                    if (!file3.isDirectory()) {
                                        file3.mkdirs();
                                    }
                                }
                            }
                        } else {
                            file2.mkdirs();
                            file3.mkdirs();
                        }
                    }
                } else {
                    file1.mkdir();
                    file2.mkdir();
                    file3.mkdir();
                }
            }catch (Exception e){
                log.error("=======================创建文件夹失败!======================");
            }
            return filepath3;
        }
    }
    package com.jshhxx.commontoolsservice.service.ExportWord.Impl;
    
    import com.jshhxx.commontoolsservice.service.ExportWord.ExportWordService;
    import com.jshhxx.commontoolsservice.word.MapperTest;
    import freemarker.template.Configuration;
    import freemarker.template.Template;
    import freemarker.template.TemplateException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.io.*;
    
    /**
     * @author 一只会飞的猪
     * @dis   查询数据导出word文档
     * */
    
    @Service
    public class ExportWordServiceImpl  implements ExportWordService {
    
        @Autowired
        private MapperTest mapperTestm;
    
        private Configuration configuration =new Configuration();
        // 将数据导入到模板word中,并生成word文档
        public void createWord(String templatePath, String templateName,
                               Object dataMap, Writer out) {
            try {
                Template t = getTemplate(templatePath, templateName);
                t.process(dataMap, out);
                out.close();
            } catch (IOException e) {
                System.out.println(e);
            } catch (TemplateException e) {
                System.out.println(e);
            } finally {
                try {
                    out.close();
                } catch (IOException e) {
                    System.out.println(e);
                }
            }
        }
        // 模板加载
        private Template getTemplate(String templatePath, String templateName)
                throws IOException {
            configuration.setClassForTemplateLoading(this.getClass(), templatePath);
            Template t  = configuration.getTemplate(templateName);
            t.setEncoding("UTF-8");
            return t;
        }
    
    }

    这样一来就大功告成了,后面的代码讲解的比较少,因为网上很多,主要讲的就是这整个功能的开发思路.
    这里写图片描述
    这里写图片描述
    功能是做出来了,但是乱码怎么解决呢?
    告诉你们一个小技巧,部署的时候制定下编码就行了,java -jar Dfile.encoding=utf-8 **

    展开全文
  • 使用poi组件自动填充模板word内容和图片.

    
    
    前段时间为学校做了个小系统,功能里面应该有自动填写内容和填写图片的.来来回回从网上找了很多.


    最近发现有篇博文不错,可是博主有一个方法我始终没搞懂,最终综合了一下别人的方法,加上自己的研究,成功了.在这里感谢这位博主.

    原帖地址:http://huangqiqing123.iteye.com/blog/1927761


    * 使用的poi是 3.8版本 需要xbean.jar 和 geronimo-stax-api_1.0_spec-1.0.jar 以及org.apache.commons.logging_1.0.4.v200706111724.jar 支持

    *工具运行环境必须为Office 2007 教训惨痛啊,一直用2013结果解析结果一直不正确,换成07就好了   

    *文档格式为docx 如果doc应该不能用.


    初始模板文档



    填充完成



    测试类:

    package com.wheal.classes;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    import org.apache.poi.xwpf.usermodel.XWPFDocument;
    public class Test {
    	public static void main(String[] args) throws Exception {
    		
    		Map<String, Object> param = new HashMap<String, Object>();
    		param.put("${xueyuan}", "学院1");
    		param.put("${zhuanye}", "专业1");
    		param.put("${banji}", "120506");
    		param.put("${xingming}", "王");
    		param.put("${xuehao}", "2012");
    		param.put("${timu}", "题目1");
    		param.put("${taidu}", "5");
    		param.put("${lilun}", "10");
    		param.put("${luwen}", "5");
    		param.put("${zhiliang}", "28");
    		param.put("${zongfen}", "60");
    		Map<String,Object> header = new HashMap<String, Object>();
    		header.put("width", 100);
    		header.put("height", 50);
    		header.put("type", "jpg");
    		header.put("content", "d:\\qianming3.jpg");
    		param.put("{qianzi}",header);
    		XWPFDocument doc = WordUtil.generateWord(param, "d:\\bs.docx");
    		FileOutputStream fopts = new FileOutputStream("d:/2.docx");
    		doc.write(fopts);
    		fopts.close();
    	}
    }
    
    工具类

    package com.wheal.classes;
    
    import java.io.ByteArrayInputStream;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    import org.apache.poi.POIXMLDocument;
    import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
    import org.apache.poi.openxml4j.opc.OPCPackage;
    import org.apache.poi.xwpf.usermodel.XWPFDocument;
    import org.apache.poi.xwpf.usermodel.XWPFParagraph;
    import org.apache.poi.xwpf.usermodel.XWPFRun;
    import org.apache.poi.xwpf.usermodel.XWPFTable;
    import org.apache.poi.xwpf.usermodel.XWPFTableCell;
    import org.apache.poi.xwpf.usermodel.XWPFTableRow;
    import org.apache.xmlbeans.XmlException;
    import org.apache.xmlbeans.XmlToken;
    import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
    import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
    import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
    
    /**
     * 适用于word 2007
     * poi 版本 3.7
     */
    public class WordUtil {
    
    	/**
    	 * 根据指定的参数值、模板,生成 word 文档
    	 * @param param 需要替换的变量
    	 * @param template 模板
    	 */
    	public static XWPFDocument generateWord(Map<String, Object> param, String template) {
    		XWPFDocument doc = null;
    		try {
    			OPCPackage pack = POIXMLDocument.openPackage(template);
    			doc = new CustomXWPFDocument(pack);
    			if (param != null && param.size() > 0) {
    				
    				//处理段落
    				List<XWPFParagraph> paragraphList = doc.getParagraphs();
    				processParagraphs(paragraphList, param, doc);
    				
    				//处理表格
    				Iterator<XWPFTable> it = doc.getTablesIterator();
    				while (it.hasNext()) {
    					XWPFTable table = it.next();
    					List<XWPFTableRow> rows = table.getRows();
    					for (XWPFTableRow row : rows) {
    						List<XWPFTableCell> cells = row.getTableCells();
    						for (XWPFTableCell cell : cells) {
    							List<XWPFParagraph> paragraphListTable =  cell.getParagraphs();
    							processParagraphs(paragraphListTable, param, doc);
    						}
    					}
    				}
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		return doc;
    	}
    	/**
    	 * 处理段落
    	 * @param paragraphList
    	 * @throws FileNotFoundException 
    	 * @throws InvalidFormatException 
    	 */
    	public static void processParagraphs(List<XWPFParagraph> paragraphList,Map<String, Object> param,XWPFDocument doc) throws InvalidFormatException, FileNotFoundException{
    		if(paragraphList != null && paragraphList.size() > 0){
    			for(XWPFParagraph paragraph:paragraphList){
    				List<XWPFRun> runs = paragraph.getRuns();
    				for (XWPFRun run : runs) {
    					String text = run.getText(0);
    					System.out.println("text=="+text);
    					if(text != null){
    						boolean isSetText = false;
    						for (Entry<String, Object> entry : param.entrySet()) {
    							String key = entry.getKey();
    							if(text.indexOf(key) != -1){
    								isSetText = true;
    								Object value = entry.getValue();
    								if (value instanceof String) {//文本替换
    									System.out.println("key=="+key);
    									text = text.replace(key, value.toString());
    								} else if (value instanceof Map) {	//图片替换
    									text = text.replace(key, "");
    									Map pic = (Map)value;
    									int width = Integer.parseInt(pic.get("width").toString());
    									int height = Integer.parseInt(pic.get("height").toString());
    									int picType = getPictureType(pic.get("type").toString());
    									String byteArray = (String) pic.get("content");
    									
    									
    									System.out.println("=="+byteArray);
    									//ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteArray);
    									
    									//int ind = doc.getAllPictures().size() - 1;
    									//doc.createPicture(ind, width , height,paragraph);
    									CTInline inline = run.getCTR().addNewDrawing().addNewInline();
    									insertPicture(doc,byteArray,inline, width, height);
    
    								}
    							}
    						}
    						if(isSetText){
    							run.setText(text,0);
    						}
    					}
    				}
    			}
    		}
    	}
    	/**
    	 * 根据图片类型,取得对应的图片类型代码
    	 * @param picType
    	 * @return int
    	 */
    	private static int getPictureType(String picType){
    		int res = CustomXWPFDocument.PICTURE_TYPE_PICT;
    		if(picType != null){
    			if(picType.equalsIgnoreCase("png")){
    				res = CustomXWPFDocument.PICTURE_TYPE_PNG;
    			}else if(picType.equalsIgnoreCase("dib")){
    				res = CustomXWPFDocument.PICTURE_TYPE_DIB;
    			}else if(picType.equalsIgnoreCase("emf")){
    				res = CustomXWPFDocument.PICTURE_TYPE_EMF;
    			}else if(picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")){
    				res = CustomXWPFDocument.PICTURE_TYPE_JPEG;
    			}else if(picType.equalsIgnoreCase("wmf")){
    				res = CustomXWPFDocument.PICTURE_TYPE_WMF;
    			}
    		}
    		return res;
    	}
    	/**
    	 * 将输入流中的数据写入字节数组
    	 * @param in
    	 * @return
    	 */
    	public static byte[] inputStream2ByteArray(InputStream in,boolean isClose){
    		byte[] byteArray = null;
    		try {
    			int total = in.available();
    			byteArray = new byte[total];
    			in.read(byteArray);
    		} catch (IOException e) {
    			e.printStackTrace();
    		}finally{
    			if(isClose){
    				try {
    					in.close();
    				} catch (Exception e2) {
    					System.out.println("关闭流失败");
    				}
    			}
    		}
    		return byteArray;
    	}
    	
    	/**
    	    * insert Picture
    	    * @param document
    	    * @param filePath
    	    * @param inline
    	    * @param width
    	    * @param height
    	    * @throws InvalidFormatException
    	    * @throws FileNotFoundException
    	    */
    	   private static void insertPicture(XWPFDocument document, String filePath,
    	                              CTInline inline, int width,
    	                              int height) throws InvalidFormatException,
    	                                                 FileNotFoundException {
    	       document.addPictureData(new FileInputStream(filePath),XWPFDocument.PICTURE_TYPE_PNG);
    	       int id = document.getAllPictures().size() - 1;
    	       final int EMU = 9525;
    	       width *= EMU;
    	       height *= EMU;
    	       String blipId =
    	           document.getAllPictures().get(id).getPackageRelationship().getId();
    	       String picXml = getPicXml(blipId, width, height);
    	       XmlToken xmlToken = null;
    	       try {
    	           xmlToken = XmlToken.Factory.parse(picXml);
    	       } catch (XmlException xe) {
    	           xe.printStackTrace();
    	       }
    	       inline.set(xmlToken);
    	       inline.setDistT(0);
    	       inline.setDistB(0);
    	       inline.setDistL(0);
    	       inline.setDistR(0);
    	       CTPositiveSize2D extent = inline.addNewExtent();
    	       extent.setCx(width);
    	       extent.setCy(height);
    	       CTNonVisualDrawingProps docPr = inline.addNewDocPr();
    	       docPr.setId(id);
    	       docPr.setName("IMG_" + id);
    	       docPr.setDescr("IMG_" + id);
    	   }
    	   /**
    	    * get the xml of the picture
    	    * @param blipId
    	    * @param width
    	    * @param height
    	    * @return
    	    */
    	   private static String getPicXml(String blipId, int width, int height) {
    	       String picXml =
    	           "" + "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">" +
    	           "   <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
    	           "      <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
    	           "         <pic:nvPicPr>" + "            <pic:cNvPr id=\"" + 0 +
    	           "\" name=\"Generated\"/>" + "            <pic:cNvPicPr/>" +
    	           "         </pic:nvPicPr>" + "         <pic:blipFill>" +
    	           "            <a:blip r:embed=\"" + blipId +
    	           "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>" +
    	           "            <a:stretch>" + "               <a:fillRect/>" +
    	           "            </a:stretch>" + "         </pic:blipFill>" +
    	           "         <pic:spPr>" + "            <a:xfrm>" +
    	           "               <a:off x=\"0\" y=\"0\"/>" +
    	           "               <a:ext cx=\"" + width + "\" cy=\"" + height +
    	           "\"/>" + "            </a:xfrm>" +
    	           "            <a:prstGeom prst=\"rect\">" +
    	           "               <a:avLst/>" + "            </a:prstGeom>" +
    	           "         </pic:spPr>" + "      </pic:pic>" +
    	           "   </a:graphicData>" + "</a:graphic>";
    	       return picXml;
    	   }
    	
    }
    



    展开全文
  • 字节输入输出流:FileInputStream / FileOutputStream 字符输入输出流:FileReader / FileWriter 区别: 1.字节输入输出流: 读入外部文件的时候是按字节单位读取的 写出外部文件的时候是按字节直接写入文件中...

    分类:IO流的分类

    1. 字节输入输出流:FileInputStream / FileOutputStream
    2. 字符输入输出流:FileReader / FileWriter

    区别:

    1.字节输入输出流:

    • 读入外部文件的时候是按字节单位读取的
    • 写出外部文件的时候是按字节直接写入文件中,无需经过缓存,直接修改文件

    2.字符输入输出流:

    • 读入外部文件的时候是按字符单位读取的
    • 先写出到缓存中,然后刷新后写入文件,如果写二进制文件的话会出现文件损坏而无法打开的情况。

    什么是二进制文件呢?

    通俗易懂的说就是:Windows自带的记事本不能读懂的文件(打开乱码),如:图片,Word文件等

    如果你还是分不清什么是二进制文件,没关系,我们都用字节流去读写文件就行了。

    实例:在相对路径里复制 源文件(1.pptx) 到 目标文件(xieqibiao.pptx) 中

    代码如下:

     //复制Word二进制文件,二进制文件就是Windows的记事本读不懂的文件,打开乱码的那种
            //1.创建字节输入流
            FileInputStream fis = new FileInputStream("1.pptx");
            //2.创建字节输出流
            FileOutputStream foStream = new FileOutputStream("xieqibiao.pptx");
            //3.复制文件
            int len = 0;//用来接收读出来的字符长度
            byte[] bys = new byte[1024];//一般长度设置为1024的整数倍
            while((len = fis.read(bys)) != -1) {//当读到还有字节的时候,写文件输出
                foStream.write(bys,0,len);//读到多少写多少
            }
            //4.关闭资源
            fis.close();
            foStream.close();

    进阶:高效输入输出 -- 字符缓冲流

    实例:

    代码如下:

    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    
    /*
     * BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。 
     * BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
     */
    public class BufferedStreamDemo {
    	public static void main(String[] args) throws IOException {
    		//创建输出缓冲流对象
    		/*
    		BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
    		bw.write("hello");
    		//bw.flush();
    		bw.close();
    		*/
    		
    		//创建输入缓冲流对象
    		BufferedReader br = new BufferedReader(new FileReader("FileWriterDemo.java"));
    		
    		/*
    		//一次读写一个字符
    		int ch;
    		while((ch=br.read())!=-1){
    			System.out.print((char)ch);
    		}
    		*/
    		
    		//一次读写一个字符数组
    		char[] chs = new char[1024];
    		int len;
    		while((len=br.read(chs))!=-1) {
    			System.out.print(new String(chs,0,len));
    		}
    		
    		//释放资源
    		br.close();
    		
    	}
    }

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    展开全文
  • java读取word文档里面的内容(包括doc和docx格式)

    千次阅读 热门讨论 2019-11-30 20:19:47
    java读取word文档里面的内容(包括doc和docx格式) java读取word文档里面的内容(包括doc和docx格式),使用POI架包 使用的POI架包如下 poi-3.16.jar poi-examples-3.16.jar poi-excelant-3.16.jar poi-ooxml-3.16.jar ...

    java读取word文档里面的内容(包括doc和docx格式)

    java读取word文档里面的内容(包括doc和docx格式),使用POI架包

    使用的POI架包如下
    poi-3.16.jar
    poi-examples-3.16.jar
    poi-excelant-3.16.jar
    poi-ooxml-3.16.jar
    poi-ooxml-schemas-3.16.jar
    poi-scratchpad-3.16.jar

    目前POI的最新发布版本是3.10_FINAL.该版本保护的jar包有:
    在这里插入图片描述
    很多人都困惑POI那么多Jar到底应该导入哪一个。

    实际上很多时候我们只利用POI来操作Excel。甚至只用xls这一种格式。

    那么就没有必要全部都导入了。具体应该使用哪个JAR包请参考以下内容:
    在这里插入图片描述

    当我们只要使用xls格式时、只要导入poi-version-yyyymmdd.jar就可以了。

    当我们还要使用xlsx格式、还要导入poi-ooxml-version-yyyymmdd.jar。

    至于poi-ooxml-schemas-version-yyyymmdd.jar这个jar基本不太会用到的。

    当我们需要操作word、ppt、viso、outlook等时需要用到poi-scratchpad-version-yyyymmdd.jar。

    读取word文档中,doc后缀的文件

    直接上代码

    //读取word文档中,doc后缀的文件
    	public static List<String> searchWordDoc(String fileUrl){
    		List<String> docList = new ArrayList<String>();
    		String content=null;
    		//读取字节流,读取文件路径
    		InputStream input = null;
    		try {
    			input = new FileInputStream(new File(request.getSession().getServletContext().getRealPath(fileUrl)));
    			WordExtractor wex = new WordExtractor(input);
    			content = wex.getText();
    			//System.out.println(content);
    			docList.add(content);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		return docList;
    	}
    
    

    将文件路径传进来,最后得到的使一个List集合,是一行一行的读取,每一行的内容对应List的下标

    读取word文档中,docx后缀的文件

    直接上代码

    	public static List<String> searchWordDocX(String fileUrl){
    		//读取文件路径
    		OPCPackage opcPackage = null;
    		String content = null;
    		List<String> docxList = new ArrayList<String>();
    		try {
    			opcPackage = POIXMLDocument.openPackage(request.getSession().getServletContext().getRealPath(fileUrl));
    			XWPFDocument xwpf = new XWPFDocument(opcPackage);
    			POIXMLTextExtractor poiText = new XWPFWordExtractor(xwpf);
    			content = poiText.getText();
    			docxList.add(content);
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		return docxList;
    	}
    
    

    将文件路径传进来,最后得到的使一个List集合,是一行一行的读取,每一行的内容对应List的下标

    最后附上jar包下载位置

    百度网盘:https://pan.baidu.com/s/1Y4BLto_mEUkS7Xhx1GJmzA
    提取码:vor5

    展开全文
  • Word文档到Asciidoc转换

    千次阅读 2017-06-22 14:18:45
    Word文档内容,需要背转换为Asciidoc。以下是我发现最有效的步骤:1. 将Word文档保存为HTML 2. 编码为UTF-8 3. 使用pandoc将HTML转换为AsciiDoc 4. 使用Sublime Text 2搜索和替换(使用一些正则表达式)去除疯狂的...
  • itext生成word文档,包含图片,其中图片直接读取路径的,也流直接转字节生成的图片
  • python抓取处理word文档

    千次阅读 2019-09-23 09:42:57
    其实python对word文档的支持不够。 为读取docx内容,可以使用以下方法: (1)利用urlopen抓取远程word docx文件; (2)将其转换为内存字节流; (3)解压缩(docx是压缩后文件); (4)将解压后文件作为xml读取 ...
  • 一、读取word文档并写入生成新的word文档: 1.使用工具包:poi-版本号.jar poi-scratchpad-版本号-beta5.jar或poi-scratchpad-版本号.jar 2.代码: import java.io.Byt...
  • android输出word文档

    千次阅读 2017-08-28 13:44:05
    最近在项目工作中,碰到一个很棘手的需求,说是要在手机端根据模板生成word文档,而且不借助第三方的软件可以查看word文档,一开始听这个需求差不多蒙了,这要怎么做,为什么不把生成word文档这个工作放在后台呢,...
  • 用word模板导出word文档

    千次阅读 热门讨论 2016-09-05 21:10:19
    项目需求要把页面上的分析结果导出为word文档,实现的办法是POI。查了一下网上很多方式都采用FreeMark,自己认为比较麻烦,所以还是采取了POI导出。之前的框架是SSH的,现在换成了Spring MVC,这次也把导出代码整理...
  • docx4j操作word文档: 动态生成表格行数并填充数据 单元格内填充图片 合并多个word文档(包含页码,纸张方向等等) 1.动态生成表格行数并填充数据 首先创建模板文件.docx,如图: 代码如下: import ...
  • word文档生成方案

    千次阅读 2018-05-07 14:49:20
    使用office软件新建一个word文件,设计好文件的格式,需要用数据来填充的地方可以使用一个变量名来占位(这里先不要freemarker标签,就使用普通的英文单词占位即可),保存。如图: ②.将上一步的word文件另存.....
  • POI操作WORD文档,生成的新文档为空白文档 ...... 目前只是找到以上现象,初步结论是表格的规格过大会对生成的WORD文件结果又影响。具体怎么解决还没有找到途径。
  • Java 将xml模板动态填充数据转换为word文档

    万次阅读 多人点赞 2018-05-30 19:56:00
     2、通过Java程序,使用freemarker.jar包转换为xml格式的word文档文件 3、使用jacob包,将xml格式的word文档文件,转换为docx格式的文档文件具体实现步骤:一、模板编辑 1、将word文档另存为xml模板: 2、模板中...
  • 取消Word文档保护权限

    千次阅读 2018-03-15 19:54:10
    最简单办法(已验证):用软件word批量去除权限工具,导入直接导出,这个软件好像只有某宝,输入word批量去除权限编辑即可,还可以,建议不懂电脑的人用以下方法有待待验证:方法一(简单有效):启动word文档,...
  • 项目中用到生成word报表,报表中表格的合并 、页眉、表格中会报表图片。然后查找了网上的资料,利用echar生成柱状图,然后已base64串的方式发给后台,在后台解析成字节数组 ,利用poi生成到word文档中。
  • Springboot 使用freemaker导出word文档

    千次阅读 2020-11-27 15:01:34
    利用freemarker导出word文档,...2 将word文档另存为xml文件,这里建议使用office来操作,wps没有实践过,网上都是推荐使用office来制作模板,具体兴趣的可以单独实践。另存为xml文件以后,使用其他工具打开xml文件..
  • 有时我们的系统中这样的需求:用户将文件上传到服务器,然后需要我们将其中一篇文档当做段落插入到另一篇文档中。 要完成这种需求,如果从头到尾由我们自己来实现的话,首先要会集成ActiveX控件,其次还要懂一些...
  • Android 使用模板生成Word文档,支持手机直接查看word

    万次阅读 热门讨论 2015-11-28 17:00:06
    最近在项目工作中,碰到一个很棘手的需求,说是要在手机端根据模板生成word文档,而且不借助第三方的软件可以查看word文档,一开始听这个需求差不多蒙了,这要怎么做,为什么不把生成word文档这个工作放在后台呢,...
  • Word打不开,如何修复word文档

    万次阅读 2012-12-14 09:18:19
    亲爱的你有没有遇到过写了好久的一篇文档突然打不开的惨剧?有没有为一篇重要的文件被损坏而苦恼几天的情形?遇到这种情况怎么办?不要急,不要急!我将会给你带来一系列的解决方案。也许你是一个坐在办公室的上班族...
  • POI解析word文档

    万次阅读 2018-07-26 15:50:02
    * 获取03版word文档标题和内容 * @param path 文件路径 * @param type 1:只获取标题;2:只获取内容;3:标题和内容都获取 * @return list * @throws IOException */ public static List<String> ...
  • poi操作word文档总结

    万次阅读 2014-06-05 17:18:43
    POI分段落生成纯Word动态模板并导入数据 导出数据,可以用word另存为xml格式的ftl文件,变量用${变量名}表示,然后在类中通过 freemarker去替换变量。...后来找到方法可以分段落读入纯word文档。要找到了word基
  • 解除Word文档保护方法汇总

    万次阅读 2007-11-04 00:48:00
    解除Word文档保护方法汇总Word的...版本:Office 2003设置Word文档保护这里,我先创建一个带文档保护的old.doc,然后随便在里面敲些东西,最好汉字,数字,字母等,再设置些它们的大小,字体颜色等.现在开始设置文档保护.执
  • word文档加密保护不能编辑问题

    千次阅读 2016-08-24 09:08:46
    方法一(简单有效):启动word文档,新建一个空白文档,执行“插入文件”命令,打开“插入文件”对话框,定位到需要解除保护的文档所在的文件夹,选中该文档,单击“插入”按钮,将加密保护的文档插入到新文档中,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 48,435
精华内容 19,374
关键字:

word文档有字节但没有内容