上周分配的任务功能是将word转化为pdf文件,在转换的过程中还需要替换文档内容(ps不会将原有内容文档更改),查询了一些资料发现java还是蛮难实现的,资料也是不多的,尤其我们的环境还是k8s里部署,就增大了很多困难,实践了很久最终成功将word转换成pdf文件了。

首先给我的word地址是url方式的地址,"http://ip/文件名称.docx"的http方式,我需要请求这个地址转换成inputStream输入流,再用word流转换成pdf,转换成pdf文件以后上传到ftp中,供nginx映射以http形式访问。

1.操作word与pdf的包

     <!-- ftp -->
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.3</version>
        </dependency>

        <!-- word转换成pdf的工具包-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.14</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>3.14</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.14</version>
        </dependency>

        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>xdocreport</artifactId>
            <version>1.0.6</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>3.14</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>ooxml-schemas</artifactId>
            <version>1.3</version>
        </dependency>

        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.11.3</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-support</artifactId>
            <version>2.1.8</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>com.lowagie</groupId>
            <artifactId>itext</artifactId>
            <version>2.1.7</version>
        </dependency>

        <dependency>
            <groupId>com.lowagie</groupId>
            <artifactId>itext-rtf</artifactId>
            <version>2.1.7</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
        <!-- word转换成pdf的工具包-->

2.根据url路径获取输入流

 /**
     * 根据url路径获取输入流
     *
     * @param strUrl http://192.168.7.115:30020/ceshi.docx
     * @return
     */
    public InputStream getInputStreamByUrl(String strUrl) {
        InputStream inputStream = null;
        try {
            URL url = new URL(strUrl);
            conn = (HttpURLConnection) url.openConnection();
            //以Post方式提交表单,默认get方式
            conn.setRequestMethod("GET");
            conn.setDoInput(true);
            conn.setDoOutput(true);
            // post方式不能使用缓存
            conn.setUseCaches(false);
            //连接指定的资源
            conn.connect();
            //获取网络输入流
            inputStream = conn.getInputStream();
            return inputStream;
        } catch (Exception e) {
            log.error("getInputStreamByUrl 异常,exception is {}", e);
            urlClose();
            inputStreamClose(inputStream);
        }
        return null;
    }

3.用word流转换pdf文件

 /**
     * 用word流转换pdf文件
     *
     * @param modelBase 实体属性
     * @param results   替换内容的数据
     */
    public String wordtoPdf(GsaModelBase modelBase, List<GsaModelMethodResult> results) {
        String filename = null;
        if (modelBase.getFilename() != null) {
            int index = modelBase.getFilename().indexOf(".");
            filename = "/" + modelBase.getFilename().substring(0, index) + ".pdf";
        }
        // 获取文档输入流
        InputStream intstream = getInputStreamByUrl(modelBase.getFileurl());
        PdfOptions options = PdfOptions.create();
        // 字体文件放入项目中并读取项目路径
        ClassPathResource classPathResource = new ClassPathResource("fort/SIMSUN.TTC,1");
        log.info("字体路径:{}", classPathResource.getPath());
        // 设置字体,必要没有此代码部署到容器里中文将不显示
        options.fontProvider(new IFontProvider() {
            public Font getFont(String familyName, String encoding, float size, int style, Color color) {
                try {
                    BaseFont bfChinese = BaseFont.createFont(classPathResource.getPath(), BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
                    com.lowagie.text.Font fontChinese = new com.lowagie.text.Font(bfChinese, size, style, color);
                    if (familyName != null)
                        fontChinese.setFamily(familyName);
                    return fontChinese;
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                } finally {
                    // 释放资源
                    urlClose();
                    inputStreamClose(intstream);
                }
            }
        });
        try {
            // 输出地址,此地址为容器根目录
            OutputStream target = new FileOutputStream(filename);
            // 替换文档内容
            Map<String, String> params = new HashMap<String, String>();
            params.put("广东", "北京");
            // 将word转换成pdf
            WordToPDFUtil.wordConverterToPdf(intstream, target, options, params);
            log.info("target:" + target);
            //将转换pdf的容器路径转换stream
            File file = new File(filename);
            InputStream in = new FileInputStream(file);
            //pdf文件上传到ftp里,为了外部nginx访问。
            boolean isSuccess = ftpUtil.uploadFileToFtp(in, filename.replace("/", ""), filePath);
            if (isSuccess) {
                log.info("上传成功!");
            }
            // 删除容器中的文件
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 释放资源
            urlClose();
            inputStreamClose(intstream);
        }
        return filename;
    }

 4.释放流和连接方式

    /**
     * 关闭HttpURLConnection
     */
    public void urlClose() {
        if (conn != null) {
            conn.disconnect();
        }
    }

    /**
     * 关闭InputStream
     *
     * @param inputStream
     */
    public void inputStreamClose(InputStream inputStream) {
        try {
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

5.字体文件存放位置,放在resource下面就好了

6.将word文档转换pdf的工具类

package gsa.geographic.land.util;

import com.baomidou.mybatisplus.toolkit.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.xwpf.converter.pdf.PdfConverter;
import org.apache.poi.xwpf.converter.pdf.PdfOptions;
import org.apache.poi.xwpf.usermodel.*;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author df
 * @Date 2020/2/20 16:35
 * @Version 1.0
 */
public class WordToPDFUtil {
    /**
     * 将word文档, 转换成pdf, 中间替换掉变量
     *
     * @param source 源为word文档, 必须为docx文档
     * @param target 目标输出
     * @param params 需要替换的变量
     * @throws Exception
     */
    public static void wordConverterToPdf(InputStream source,
                                          OutputStream target, Map<String, String> params) throws Exception {
        wordConverterToPdf(source, target, null, params);
    }

    /**
     * 将word文档, 转换成pdf, 中间替换掉变量
     *
     * @param source  源为word文档, 必须为docx文档
     * @param target  目标输出
     * @param params  需要替换的变量
     * @param options PdfOptions.create().fontEncoding( "windows-1250" ) 或者其他
     * @throws Exception
     */
    public static void wordConverterToPdf(InputStream source, OutputStream target,
                                          PdfOptions options,
                                          Map<String, String> params) throws Exception {
        XWPFDocument doc = new XWPFDocument(source);
        paragraphReplace(doc.getParagraphs(), params);
        for (XWPFTable table : doc.getTables()) {
            for (XWPFTableRow row : table.getRows()) {
                for (XWPFTableCell cell : row.getTableCells()) {
                    paragraphReplace(cell.getParagraphs(), params);
                }
            }
        }
        PdfConverter.getInstance().convert(doc, target, options);
    }

    /**
     * 替换段落中内容
     */
    private static void paragraphReplace(List<XWPFParagraph> paragraphs, Map<String, String> params) {
        if (MapUtils.isNotEmpty(params)) {
            for (XWPFParagraph p : paragraphs) {
                for (XWPFRun r : p.getRuns()) {
                    r.setFontFamily("宋体");
                    String content = r.getText(r.getTextPosition());
                    System.out.println(content);
                    if (StringUtils.isNotEmpty(content) && params.containsKey(content)) {
                        r.setText(params.get(content), 0);
                    }
                }
            }
        }
    }

}

7.ftp上传代码

    Logger logger = LoggerFactory.getLogger(FTPUtil.class);
    private String LOCAL_CHARSET = "GBK";

    // 该目录不存在
    public static final String DIR_NOT_EXIST = "该目录不存在";

    // 该目录下没有文件
    public static final String DIR_CONTAINS_NO_FILE = "该目录下没有文件";

    // ftp服务器地址
    @Value("${ftp.ip}")
    private String hostname;

    // ftp服务器端口
    @Value("${ftp.port}")
    private int port;

    // ftp登录账号
    @Value("${ftp.username}")
    private String username;

    // ftp登录密码
    @Value("${ftp.password}")
    private String password;

    // ftp保存目录
    @Value("${ftp.filePath}")
    private String filePath; // 文件

    /**
     * 初始化ftp服务器
     */
    public FTPClient getFtpClient() {
        FTPClient ftpClient = new FTPClient();
        ftpClient.setControlEncoding("utf-8");

        try {
            ftpClient.setDataTimeout(1000 * 120);//设置连接超时时间
            logger.info("connecting...ftp服务器:" + hostname + ":" + port);
            ftpClient.connect(hostname, port); // 连接ftp服务器
            ftpClient.login(username, password); // 登录ftp服务器
            int replyCode = ftpClient.getReplyCode(); // 是否成功登录服务器
            if (FTPReply.isPositiveCompletion(ftpClient.sendCommand(
                    "OPTS UTF8", "ON"))) {      // 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
                LOCAL_CHARSET = "UTF-8";
            }
            if (!FTPReply.isPositiveCompletion(replyCode)) {
                logger.error("connect failed...ftp服务器:" + hostname + ":" + port);
            }
            logger.info("connect successfu...ftp服务器:" + hostname + ":" + port);
        } catch (MalformedURLException e) {
            logger.error(e.getMessage(), e);
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        return ftpClient;
    }


 /**
     * 文件上传根据流文件
     *
     * @param inputStream 文件流
     * @param fileName
     * @param path
     * @return
     */
    public boolean uploadFileToFtp(InputStream inputStream, String fileName, String path) {
        boolean isSuccess = false;
        FTPClient ftpClient = getFtpClient();
        try {
            if (ftpClient.isConnected()) {
                ftpClient.setFileType(FTP.BINARY_FILE_TYPE);//设置上传文件类型为二进制,否则将无法打开文件
                logger.info("开始上传文件到FTP,文件名称{}:,上传路径:{}", fileName, path);
                ftpClient.makeDirectory(path);
                ftpClient.changeWorkingDirectory(path);
                //设置为被动模式(如上传文件夹成功,不能上传文件,注释这行,否则报错refused:connect  )
                ftpClient.enterLocalPassiveMode();//设置被动模式,文件传输端口设置
                ftpClient.storeFile(fileName, inputStream);
                logger.info(fileName, "{}文件上传到FTP成功");
                isSuccess = true;
                ftpClient.logout();
            } else {
                logger.error("FTP连接建立失败");
            }
        } catch (Exception e) {
            logger.error("文件上传到FTP出现异常");
            logger.error(e.getMessage(), e);
        }
        return isSuccess;
    }

以上就是全部内容,可以解决部署k8s容器中word转换pdf存储文件的地方,也可以解决k8s容器部署或linux部署word转换pdf不显示中文的问题,希望可以帮助你!

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐