广告
返回顶部
首页 > 资讯 > 后端开发 > Python >SpringBoot如何实现word文档转pdf
  • 403
分享到

SpringBoot如何实现word文档转pdf

2024-04-02 19:04:59 403人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录一.背景二.方案选择1.Spire.Doc for Java方案2.docx4j方案3.jodconverter+LibreOffice 方案4.其他三.实操1.docx4j2.

一.背景

项目中有个需求大体意思是,上传一个Word模板,根据word模板合成word文件,再将word文件转为pdf

二.方案选择

1.Spire.Doc for Java方案

Spire.Doc for Java这个是商用收费的,不过api文档丰富且集成简单,免费版仅支持3页转换。类似的还有ITEXT,这个商用也是受限制的。

2.docx4j方案

开源可商用,仅支持docx格式的word。

3.jodconverter+LibreOffice 方案

开源可商用,调用本地office服务,进行pdf转换,类似的还有jodconverter+openOffice。

4.其他

至于其他的由于不支持跨平台不做考虑。

三.实操

1.docx4j

首先尝试了docx4j,因为docx4j本身支持模板替换的操作,可一次性做替换及文档类型转换,而且仅支持docx类型,对于本次需求问题不大。

1.依赖仅需要一个即可

<dependency>
    <groupId>org.docx4j</groupId>
    <artifactId>docx4j-export-fo</artifactId>
    <version>6.1.0</version>
</dependency>

2.主要代码

@Slf4j
public class PdfUtil {
    public static <T> void exportByLocalPath(httpservletResponse response, String fileName, String path, Map<String,String> params){
        try (InputStream in = PdfUtil.class.getClassLoader().getResourceAsStream(path)) {
            convertDocxToPdf(in, response,fileName,params);
        } catch (Exception e) {
            log.error("docx文档转换为PDF失败", e.getMessage());
        }
    }
    
    public static void convertDocxToPdf(InputStream in, HttpServletResponse response, String fileName, Map<String,String> params) throws Exception {
        response.setContentType("application/pdf");
         String fullFileName = new String(fileName.getBytes(), StandardCharsets.ISO_8859_1);
        response.setHeader("Content-disposition", "attachment;filename=" + fullFileName + ".pdf");
        WordprocessingMLPackage wmlPackage = WordprocessingMLPackage.load(in);
        if (params!=null&&!params.isEmpty()) {
            MainDocumentPart documentPart = wmlPackage.getMainDocumentPart();
            cleanDocumentPart(documentPart);
            documentPart.variableReplace(params);
        }
        setFontMapper(wmlPackage);
        Docx4J.toPDF(wmlPackage,response.getOutputStream());
    }
    
    public static boolean cleanDocumentPart(MainDocumentPart documentPart) throws Exception {
        if (documentPart == null) {
            return false;
        }
        Document document = documentPart.getContents();
        String wmlTemplate =
                XmlUtils.marshaltoString(document, true, false, Context.jc);
        document = (Document) XmlUtils.unwrap(DocxVariableClearUtil.doCleanDocumentPart(wmlTemplate, Context.jc));
        documentPart.setContents(document);
        return true;
    }
    
    private static void setFontMapper(WordprocessingMLPackage mlPackage) throws Exception {
        Mapper fontMapper = new IdentityPlusMapper();
        fontMapper.put("隶书", PhysicalFonts.get("LiSu"));
        fontMapper.put("宋体", PhysicalFonts.get("SimSun"));
        fontMapper.put("微软雅黑", PhysicalFonts.get("Microsoft Yahei"));
        fontMapper.put("黑体", PhysicalFonts.get("SimHei"));
        fontMapper.put("楷体", PhysicalFonts.get("KaiTi"));
        fontMapper.put("新宋体", PhysicalFonts.get("NSimSun"));
        fontMapper.put("华文行楷", PhysicalFonts.get("STXingkai"));
        fontMapper.put("华文仿宋", PhysicalFonts.get("STFangsong"));
        fontMapper.put("宋体扩展", PhysicalFonts.get("simsun-extB"));
        fontMapper.put("仿宋", PhysicalFonts.get("FangSong"));
        fontMapper.put("仿宋_GB2312", PhysicalFonts.get("FangSong_GB2312"));
        fontMapper.put("幼圆", PhysicalFonts.get("YouYuan"));
        fontMapper.put("华文宋体", PhysicalFonts.get("STSong"));
        fontMapper.put("华文中宋", PhysicalFonts.get("STZhongsong"));
        mlPackage.setFontMapper(fontMapper);
    }
}

清除工具类,用于处理占位符替换不生效的问题,这里参考文章

public class DocxVariableClearUtil {
    
    private static final Pattern XML_PATTERN = Pattern.compile("<[^>]*>");
    private DocxVariableClearUtil() {
    }
    
    private static final char PREFIX = '$';
    
    private static final char LEFT_BRACE = '{';
    
    private static final char RIGHT_BRACE = '}';
    
    private static final int NONE_START = -1;
    
    private static final int NONE_START_INDEX = -1;
    
    private static final int PREFIX_STATUS = 1;
    
    private static final int LEFT_BRACE_STATUS = 2;
    
    private static final int RIGHT_BRACE_STATUS = 3;
    
    public static Object doCleanDocumentPart(String wmlTemplate, JAXBContext jc) throws JAXBException {
        // 进入变量块位置
        int curStatus = NONE_START;
        // 开始位置
        int keyStartIndex = NONE_START_INDEX;
        // 当前位置
        int curIndex = 0;
        char[] textCharacters = wmlTemplate.toCharArray();
        StringBuilder documentBuilder = new StringBuilder(textCharacters.length);
        documentBuilder.append(textCharacters);
        // 新文档
        StringBuilder newDocumentBuilder = new StringBuilder(textCharacters.length);
        // 最后一次写位置
        int lastWriteIndex = 0;
        for (char c : textCharacters) {
            switch (c) {
                case PREFIX:
                    // 不管其何状态直接修改指针,这也意味着变量名称里面不能有PREFIX
                    keyStartIndex = curIndex;
                    curStatus = PREFIX_STATUS;
                    break;
                case LEFT_BRACE:
                    if (curStatus == PREFIX_STATUS) {
                        curStatus = LEFT_BRACE_STATUS;
                    }
                    break;
                case RIGHT_BRACE:
                    if (curStatus == LEFT_BRACE_STATUS) {
                        // 接上之前的字符
                        newDocumentBuilder.append(documentBuilder.substring(lastWriteIndex, keyStartIndex));
                        // 结束位置
                        int keyEndIndex = curIndex + 1;
                        // 替换
                        String rawKey = documentBuilder.substring(keyStartIndex, keyEndIndex);
                        // 干掉多余标签
                        String mappingKey = XML_PATTERN.matcher(rawKey).replaceAll("");
                        if (!mappingKey.equals(rawKey)) {
                            char[] rawKeyChars = rawKey.toCharArray();
                            // 保留原格式
                            StringBuilder rawStringBuilder = new StringBuilder(rawKey.length());
                            // 去掉变量引用字符
                            for (char rawChar : rawKeyChars) {
                                if (rawChar == PREFIX || rawChar == LEFT_BRACE || rawChar == RIGHT_BRACE) {
                                    continue;
                                }
                                rawStringBuilder.append(rawChar);
                            }
                            // 要求变量连在一起
                            String variable = mappingKey.substring(2, mappingKey.length() - 1);
                            int variableStart = rawStringBuilder.indexOf(variable);
                            if (variableStart > 0) {
                                rawStringBuilder = rawStringBuilder.replace(variableStart, variableStart + variable.length(), mappingKey);
                            }
                            newDocumentBuilder.append(rawStringBuilder.toString());
                        } else {
                            newDocumentBuilder.append(mappingKey);
                        }
                        lastWriteIndex = keyEndIndex;
                        curStatus = NONE_START;
                        keyStartIndex = NONE_START_INDEX;
                    }
                default:
                    break;
            }
            curIndex++;
        }
        // 余部
        if (lastWriteIndex < documentBuilder.length()) {
            newDocumentBuilder.append(documentBuilder.substring(lastWriteIndex));
        }
        return XmlUtils.unmarshalString(newDocumentBuilder.toString(), jc);
    }
}

2.poi-tl+jodconverter+LibreOffice 方案

poi-tl这个是专门用来进行word模板合成的开源库,文档很详细。

LibreOffice 下载最新的稳定版本即可。

1.maven依赖

		<!-- word合成 -->
		<!-- 这里注意版本,1.5版本依赖的poi 3.x的版本 -->
		<dependency>
			<groupId>com.deepoove</groupId>
			<artifactId>poi-tl</artifactId>
			<version>1.5.1</version>
		</dependency>
		<!-- jodconverter  word转pdf -->
		<!-- jodconverter-core这个依赖,理论上不用加的,jodconverter-local已经依赖了,但测试的时候不添加依赖找不到 -->
		<dependency>
			<groupId>org.jodconverter</groupId>
			<artifactId>jodconverter-core</artifactId>
			<version>4.2.0</version>
		</dependency>
		<dependency>
			<groupId>org.jodconverter</groupId>
			<artifactId>jodconverter-local</artifactId>
			<version>4.2.0</version>
		</dependency>
		<dependency>
			<groupId>org.jodconverter</groupId>
			<artifactId>jodconverter-spring-boot-starter</artifactId>
			<version>4.2.0</version>
		</dependency>
		<!--  工具类,非必须 -->
		<dependency>
			<groupId>cn.hutool</groupId>
			<artifactId>hutool-all</artifactId>
			<version>5.4.3</version>
		</dependency>

2.主要代码

JodConverterConfig配置类

@Configuration
public class JodConverterConfig {
    @Autowired
    private OfficeManager officeManager;
    @Bean
    public DocumentConverter documentConverter() {
        return LocalConverter.builder()
                .officeManager(officeManager)
                .build();
    }
}

yml配置文件

jodconverter:
  local:
    enabled: true
    office-home: "C:\\Program Files\\LibreOffice"

PdfService合成导出代码

@Slf4j
@Component
public class PdfService {
    @Autowired
    private DocumentConverter documentConverter;
    public  void docxToPDF(InputStream inputStream,HttpServletResponse response,String fileName) {
        response.setContentType("application/pdf");
        try {
            String fullFileName = new String(fileName.getBytes(), StandardCharsets.ISO_8859_1);
            response.setHeader("Content-disposition","attachment;filename=\\"+fullFileName+".pdf\\");
            documentConverter
                    .convert(inputStream)
                    .as(DefaultDocumentFORMatReGIStry.DOCX)
                    .to(response.getOutputStream())
                    .as(DefaultDocumentFormatRegistry.PDF)
                    .execute();
        } catch (OfficeException |IOException e) {
           log.error("word转pdf失败:{}",e.getMessage());
        }
    }
    public void exportByLocalPath(HttpServletResponse response, String fileName, String path, Object params) throws Exception {
        BufferedOutputStream outputStream = null;
        BufferedInputStream wordInputStream = null;
        try (InputStream in = PdfService.class.getClassLoader().getResourceAsStream(path)) {
            // 生成临时文件
            String outPutWordPath = System.getProperty("java.io.tmpdir").replaceAll(File.separator + "$", "") + fileName+".docx";
            File tempFile = FileUtil.touch(outPutWordPath);
            outputStream = FileUtil.getOutputStream(tempFile);
            // word模板合成写到临时文件
            WordUtil.replaceWord(outputStream, in, params);
            // word 转pdf
            wordInputStream = FileUtil.getInputStream(tempFile);
            docxToPDF(wordInputStream, response,fileName);
            // 移除临时文件
            FileUtil.del(tempFile);
        } catch (Exception e) {
            log.error("docx文档转换为PDF失败", e.getMessage());
        } finally {
            IoUtil.close(outputStream);
            IoUtil.close(wordInputStream);
        }
    }

四.结论

1.docx4j方案

  • 依赖少
  • 同时支持word合成及格式转换
  • 转化效率较差
  • 对于含样式及图片转换不友好,容易排版混乱

2.jodconverter+LibreOffice 方案

  • 操作稳定
  • 转换效率快
  • 集成依赖设置较多
  • 依赖本地服务
  • LibreOffice打开word可能排版样式错乱
  • 最后考虑项目需求,最终选择了jodconverter+LibreOffice方案。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。 

--结束END--

本文标题: SpringBoot如何实现word文档转pdf

本文链接: https://www.lsjlt.com/news/153389.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • SpringBoot如何实现word文档转pdf
    目录一.背景二.方案选择1.Spire.Doc for Java方案2.docx4j方案3.jodconverter+LibreOffice 方案4.其他三.实操1.docx4j2....
    99+
    2022-11-13
  • Go语言中如何实现PDF转word文档
    Go语言PDF转word文档步骤如下:1、设置许可证信息;2、打开PDF文件;3、创建一个新的Word文档;4、遍历PDF的每一页,将每一页转换为图像,并将图像插入到Word文档中;5、保存Word文档。本教程操作系统:windows10系...
    99+
    2023-12-13
    PDF转word go语言 Golang
  • pdf文件如何转换为word文档
    这篇文章主要介绍了pdf文件如何转换为word文档,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。材料:PDF文件,电脑工具:PDF转换器(迅...
    99+
    2022-10-18
  • Python一键实现PDF文档批量转Word
    目录实现效果环境准备代码实现无论是在工作还是学习当中,大家都会遇到这样一个问题,将“PDF当中的内容(文本和图片)转换为Word的格式”,也就是说从只读转换成...
    99+
    2022-11-11
  • php如何将word文档转成PDF文件
    本文小编为大家详细介绍“php如何将word文档转成PDF文件”,内容详细,步骤清晰,细节处理妥当,希望这篇“php如何将word文档转成PDF文件”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。第一步:安装和配置...
    99+
    2023-07-05
  • 如何利用python将pdf文档转为word?
    1.前言 有些时候,我们需要将pdf文档转换为word文档进行处理,但市面上的一些pdf软件往往需要付费才能使用。那么作为一名技术人员,如何才能实现pdf转word自由? 2.准备工作 提前安装好py...
    99+
    2023-09-05
    word python pdf
  • Java实现PDF转为Word文档的示例代码
    目录代码编译环境将 PDF 转换为固定布局的 Doc/Docx 文档完整代码将 PDF 转换为流动形态的 Doc/Docx 文档完整代码效果图众所周知,PDF文档除了具有较强稳定性和...
    99+
    2023-01-28
    Java实现PDF转Word Java PDF转Word Java PDF Word
  • 如何在iPhone上将Word文档转换为PDF
    无论是银行对账单还是求职简历,在某些场景下,您都需要在线提交 PDF 格式的文件。大多数文档仍然以Word格式在iPhone上存储的大部分时间。但是iPhone上没有专用的默认应用程序可以直接将Word文档转换为pdf格式,安装任何不安全的...
    99+
    2023-07-12
  • Word转PDF功能实现,文档转换工具通过PHP开发
    最近比较火的文档转换工具相信大家都听说过,但是怎么实现呢? 通过该接口可以将图片、word、excel、ppt等文档转换为pdf格式的文件 可以将Office(Word,Excel,PowerPoint)文件转换为PDF。 转换文件内容、格...
    99+
    2023-09-02
    php http 开发语言
  • SpringBoot+Thymeleaf实现生成PDF文档
    目录前言一、引入依赖二、application.yml配置三、PDF相关配置四、Controller五、生成PDF文件响应效果前言 温馨提示:本博客使用Thymeleaf模板引擎实现...
    99+
    2022-11-13
  • Java如何实现无损Word转PDF
    这篇文章主要介绍“Java如何实现无损Word转PDF”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java如何实现无损Word转PDF”文章能帮助大家解决问题。word转pdf实现思路代码实现主要...
    99+
    2023-07-02
  • 基于pdf2docx模块怎么用Python实现批量将PDF转Word文档
    这篇“基于pdf2docx模块怎么用Python实现批量将PDF转Word文档”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“...
    99+
    2023-07-06
  • Python批量实现Word、EXCLE、PPT转PDF文件
     一、绪论背景         在日常办公和文档处理中,有时我们需要将多个Word文档、Excel表格或PPT演示文稿转换为PDF文件。将文档转换为PDF格式的好处是它可以保留文档的布局和格式,并且可以在不同平台上进行方便的查看和共享。 ...
    99+
    2023-09-25
    win32com 办公自动化 批量实现
  • 如何用php把word转pdf文件
    这篇文章主要介绍了如何用php把word转pdf文件的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇如何用php把word转pdf文件文章都会有所收获,下面我们一起来看看吧。PHP和LibreOffice最好的文...
    99+
    2023-07-05
  • 基于Python实现网页文章转PDF文档
    我们有时候看到一篇好的文章,想去保存下来,传统方式一般是收藏书签、复制粘贴到文档或者直接复制链接保存,但这样一次两次还好,数量多了,比较麻烦不说,还可能不好找~ 这个时候,Pyth...
    99+
    2022-11-11
  • caj文件如何转换成word文档
    今天小编给大家分享一下caj文件如何转换成word文档的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。caj文件怎么转换成wo...
    99+
    2023-07-04
  • 如何将php文件转为word文档
    本篇内容介绍了“如何将php文件转为word文档”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!准备工作在开始转换之前,您需要确保已经安装了 ...
    99+
    2023-07-05
  • Java如何实现PDF转HTML/Word/Excel/PPT/PNG
    这篇文章主要介绍了Java如何实现PDF转HTML/Word/Excel/PPT/PNG的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java如何实现PDF转HTML/Word/Excel/PPT/PNG文章都...
    99+
    2023-06-30
  • 如何将HTML文件转换成Word文档
    随着互联网和信息技术的不断进步,越来越多的人开始使用网页来展示和传递信息。然而,有些情况下我们需要将网页的内容转换成Word文档,例如需要打印文档、需要在Word中编辑等。本文将介绍如何将HTML文件转换成Word文档。一、使用在线转换工具...
    99+
    2023-05-14
  • JAVA实现PDF转HTML文档的示例代码
    本文是基于PDF文档转PNG图片,然后进行图片拼接,拼接后的图片转为base64字符串,然后拼接html文档写入html文件实现PDF文档转HTML文档。 引入Maven依赖 &...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作