pdf与word互相转换

工作中经常遇到pdf与word转换场景,我们找到一个好用的工具。

pom:

<dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.4.2</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf.tool</groupId>
            <artifactId>xmlworker</artifactId>
            <version>5.4.1</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>

        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>flying-saucer-pdf</artifactId>
            <version>9.0.3</version>
        </dependency>

工具类:PdfUtil

public class PdfUtil {
    private static final Logger logger = LoggerFactory.getLogger(PdfUtil.class);

    /**
     * 字体文件目录
     */
    public static final String FONTS_PATH = "/fonts";


    private PdfUtil() {}



    public static String createPdf(String filePath, String fileName, String content) {
        return createPdf(filePath, fileName, content, null);
    }

    /**
     * 生成pdf文件
     * @param filePath
     * @param content
     * @param data
     */
    public static String createPdf(String filePath, String fileName, String content, Object data) {
        if (!FileUtil.exist(filePath)) {
            FileUtil.mkdir(filePath);
        }

        FileOutputStream outputStream=null;
        try{
            File file = FileUtil.file(filePath, fileName);
            //设置输出路径
            outputStream=new FileOutputStream(file);
            //设置文档大小
            Document document = new Document(PageSize.A4);
            PdfWriter writer = PdfWriter.getInstance(document, outputStream);

            //设置页眉页脚
            PDFHeaderFooter headerFooter=new PDFHeaderFooter();
            PDFBuilder builder = new PDFBuilder(headerFooter, data);
            builder.setPresentFontSize(10);
            writer.setPageEvent(builder);
            //输出为PDF文件
            convertToPDF(writer,document,content);
            return file.getPath();
        }catch(Exception ex){
            throw new RuntimeException("PDF export to File fail",ex);
        }finally{
            IOUtils.closeQuietly(outputStream);
        }
    }


    private static void convertToPDF(PdfWriter writer,Document document,String htmlString){
        //获取字体路径
        String fontPath = getFontsPath();
        document.open();
        try {
            XMLWorkerHelper.getInstance().parseXHtml(writer,document,
                    new ByteArrayInputStream(htmlString.getBytes("utf-8")),
                    XMLWorkerHelper.class.getResourceAsStream("/default.css"),
                    Charset.forName("UTF-8"),new XMLWorkerFontProvider(fontPath));
        } catch (IOException e) {
            logger.error("", e);
            throw new RuntimeException("PDF文件生成异常",e);
        }finally {
            if (null != document) {
                document.close();
            }
        }

    }

    /**
     * @description 获取字体设置路径
     */
    public static String getFontsPath() {
        String fontPath = System.getProperty("user.home") + FONTS_PATH;
        return fontPath;
    }
}

构建实体:PDFBuilder

public class PDFBuilder extends PdfPageEventHelper {

   private static Logger log= LoggerFactory.getLogger(PDFBuilder.class);

    //字体文件名
    private String fontFileName;
    // 基础字体对象
    private  BaseFont bf;
    // 利用基础字体生成的字体对象,一般用于生成中文文字
    private  Font fontDetail;
    //文档字体大小
    private  int fontSize = 12;
    //模板
    private  PdfTemplate template;
    //数据实体
    private  Object data;
    //页眉页脚定制接口
    private HeaderFooterBuilder headerFooterBuilder;

    private static final String FONT_FILE = "ping_fang_light.ttf";

    private static final String[] FONTS = new String[]{"ping_fang_bold.ttf","ping_fang_light.ttf","ping_fang_regular.ttf","SIMLI.TTF",
            "FZXBS_GBK.TTF","FS_GB2312.ttf","FZXBSJW.TTF"};

    //不允许空的构造方法
    private PDFBuilder() {

    }
    public PDFBuilder(HeaderFooterBuilder headerFooterBuilder) {
        this(headerFooterBuilder,null);
    }

    public PDFBuilder(HeaderFooterBuilder headerFooterBuilder, Object data) {
       this(headerFooterBuilder,data,FONT_FILE);
    }
    public PDFBuilder(HeaderFooterBuilder headerFooterBuilder, Object data, String fontFileName) {
       this(headerFooterBuilder,data,fontFileName,12);
    }

    public PDFBuilder(HeaderFooterBuilder headerFooterBuilder, Object data, String fontFileName, int fontSize) {
        this.headerFooterBuilder = headerFooterBuilder;
        this.data=data;
        this.fontFileName=fontFileName;
        this.fontSize=fontSize;
        initFontResource();
    }



    public void onOpenDocument(PdfWriter writer, Document document) {
        template = writer.getDirectContent().createTemplate(50, 50);
    }
    /**
     *
     * 关闭每页的时候,写入页眉,页脚等
     *
     */
    public void onEndPage(PdfWriter writer, Document document) {
        this.addPage(writer, document);
    }

    //加分页
    private void addPage(PdfWriter writer, Document document){
        if(headerFooterBuilder !=null){
            //1.初始化字体
            initFront();
            //2.写入页眉
            headerFooterBuilder.writeHeader(writer,document,data,fontDetail,template);
            //3.写入前半部分页脚
            headerFooterBuilder.writeFooter(writer,document,data,fontDetail,template);
        }
    }
    /**
     *
     * 关闭文档时,替换模板,完成整个页眉页脚组件
     *
     */
    public void onCloseDocument(PdfWriter writer, Document document) {
        if(headerFooterBuilder !=null){
            template.beginText();
            template.setFontAndSize(bf,fontSize);
            String replace= headerFooterBuilder.getReplaceOfTemplate(writer,document,data);
            template.showText(replace);
            template.endText();
            template.closePath();
        }
    }



    /**
     * @description 初始化字体
     */
    private void initFront(){
        if(StringUtils.isEmpty(fontFileName)){
            throw new RuntimeException("PDF文档字体未设置!");
        }
        try {
            if (bf == null) {
                //添加字体,以支持中文
                String fontPath =PdfUtil.getFontsPath() + "/" + fontFileName;
                //创建基础字体
                bf = BaseFont.createFont(fontPath,BaseFont.IDENTITY_H,BaseFont.EMBEDDED);
            }
            if (fontDetail == null) {
                fontDetail = new Font(bf, fontSize, Font.NORMAL);// 数据体字体
                log.info("PDF文档字体初始化完成!");
            }
        } catch (DocumentException e) {
            log.error("字体初始化失败{}", ExceptionUtils.getFullStackTrace(e));
            throw new RuntimeException("字体初始化失败",e);
        } catch (IOException e) {
            log.error("字体初始化失败{}", ExceptionUtils.getFullStackTrace(e));
            throw new RuntimeException("字体初始化失败",e);
        }
    }

    private void initFontResource() {
        // 字体、logo文件移动至临时目录,解决jar包运行时取不到resource目录绝对路径问题
        if (!FileUtil.exist(PdfUtil.getFontsPath())) {
            FileUtil.mkdir(PdfUtil.getFontsPath());
        }
        for(String font : FONTS) {
            String path = PdfUtil.getFontsPath() + File.separator + font;
            if (!FileUtil.exist(path)) {
                String resourceFilePath = "fonts" + File.separator + font;
                copyResourceFile(resourceFilePath, font);
            }
        }
    }
    private static void copyResourceFile(String resourceFilePath, String targetFileName) {
        copyResourceFile(resourceFilePath,targetFileName, PdfUtil.getFontsPath());
    }
    
    private static void copyResourceFile(String resourceFilePath, String targetFileName, String targetPath) {
        File targetFile = FileUtil.file(targetPath, targetFileName);
        OutputStream outputStream = null;
        if (!FileUtil.exist(targetFile)) {
            InputStream inputStream = PdfUtil.class.getClassLoader().getResourceAsStream(resourceFilePath);
            try {
                outputStream = new FileOutputStream(targetFile);
                IOUtils.copy(inputStream, outputStream);
            } catch (Exception e) {
                log.error("", e);
            } finally {
                IoUtil.close(outputStream);
                IoUtil.close(inputStream);
            }

        }
    }

    public int getPresentFontSize() {
        return fontSize;
    }

    public void setPresentFontSize(int fontSize) {
        this.fontSize = fontSize;
    }

    public String getFontFileName() {
        return fontFileName;
    }

    public void setFontFileName(String fontFileName) {
        this.fontFileName = fontFileName;
    }
}

页眉页脚相关接口和实现类:HeaderFooterBuilder

public interface HeaderFooterBuilder {


    /**
     * @description 写页眉
     */
    void writeHeader(PdfWriter writer, Document document, Object data, Font font, PdfTemplate template);
    /**
     * @description 写页脚
     */
    void writeFooter(PdfWriter writer, Document document, Object data, Font font, PdfTemplate template);

    /**
     * @description 关闭文档前,获取替换页眉页脚处设置模板的文本
     */
    String  getReplaceOfTemplate(PdfWriter writer, Document document, Object data);

}



public class PDFHeaderFooter implements HeaderFooterBuilder {
    /**
     * @param writer   PDF编写类
     * @param document PDF文档对象
     * @param data     业务数据
     * @param font     字体设置
     * @param template PDF模板
     * @description PDF页脚设置类
     */
    public void writeFooter(PdfWriter writer,
                            Document document,
                            Object data,
                            Font font,
                            PdfTemplate template) {
        if (data == null) {
            return;
        }
        int pageS = writer.getPageNumber();
        int currentPage = pageS - 1;
        if (currentPage <= 0) {
            return;
        }
        Phrase footer1 = new Phrase("页脚一", font);
        Phrase footer2 = new Phrase("页脚二" + "    " + currentPage + "/", font);

        PdfContentByte cb = writer.getDirectContent();
        ColumnText.showTextAligned(
                cb,
                Element.ALIGN_LEFT,
                footer1,
                (document.left() + 10),
                document.bottom() - 20,
                0);
        ColumnText.showTextAligned(
                cb,
                Element.ALIGN_RIGHT,
                footer2,
                (document.right() - 30),
                document.bottom() - 20, 0);

        //设置模板位置
        cb.addTemplate(template, document.right() - 30, document.bottom() - 20);

    }

    /**
     * @param writer   PDF编写类
     * @param document PDF文档对象
     * @param data     业务数据
     * @param font     字体设置
     * @param template PDF模板
     * @description PDF页头设置类
     */
    public void writeHeader(PdfWriter writer,
                            Document document,
                            Object data,
                            Font font,
                            PdfTemplate template) {

        ColumnText.showTextAligned(
                writer.getDirectContent(),
                Element.ALIGN_LEFT,
                new Phrase("", font),
                document.left(),
                document.top() + 20, 0);


    }


    /**
     * @param writer   PDF编写类
     * @param document PDF文档对象
     * @param data     业务数据
     * @description 页头、页眉设置的模板替换类
     */
    public String getReplaceOfTemplate(PdfWriter writer, Document document, Object data) {
        int total = writer.getPageNumber() - 2;
        return total + "";
    }

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值