当前位置: 代码网 > it编程>编程语言>Java > SpringBoot实现Word和PDF互相转换的操作详解

SpringBoot实现Word和PDF互相转换的操作详解

2025年12月16日 Java 我要评论
第一章:word和pdf的“爱恨情仇”1.1 初遇:两种不同的“性格”word同学:活泼开朗的编辑小王子,天生爱打扮(格式丰富),随时可以改头换面(可编

第一章:word和pdf的“爱恨情仇”

1.1 初遇:两种不同的“性格”

word同学:活泼开朗的编辑小王子,天生爱打扮(格式丰富),随时可以改头换面(可编辑),但有时候过于花哨,换个环境就“水土不服”。

pdf同学:高冷严谨的档案管理员,保持原样绝不动摇(格式固定),去哪都一个样(跨平台一致),但有点固执——“你可以看我,但别想碰我”(难以编辑)。

1.2 办公室恋情发展

  • word转pdf:word决定“从良”,放弃花哨生活,变成稳重可靠的pdf。这叫“爱的封印”——把美好定格,防止别人乱改。
  • pdf转word:pdf想要“放开自我”,尝试可编辑的生活。但这个过程就像“开盲盒”——有时候能完美转换,有时候……只能说“尽力了”。

第二章:springboot当“红娘”的准备步骤

2.1 创建springboot“婚介所”

用spring initializr创建项目,记得带上这些“彩礼”:

  • spring web (提供rest api)
  • apache poi (处理word)
  • pdfbox (处理pdf)
  • openpdf (或itext,用于pdf生成)

2.2 maven依赖配置(pom.xml)

<!-- 婚礼请柬列表 -->
<dependencies>
    <!-- springboot基础套餐 -->
    <dependency>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-web</artifactid>
    </dependency>
    
    <!-- word处理专家:apache poi全家桶 -->
    <dependency>
        <groupid>org.apache.poi</groupid>
        <artifactid>poi</artifactid>
        <version>5.2.3</version>
    </dependency>
    <dependency>
        <groupid>org.apache.poi</groupid>
        <artifactid>poi-ooxml</artifactid>
        <version>5.2.3</version>
    </dependency>
    
    <!-- pdf处理专家:pdfbox -->
    <dependency>
        <groupid>org.apache.pdfbox</groupid>
        <artifactid>pdfbox</artifactid>
        <version>2.0.27</version>
    </dependency>
    
    <!-- 另一种pdf生成选择:openpdf -->
    <dependency>
        <groupid>com.github.librepdf</groupid>
        <artifactid>openpdf</artifactid>
        <version>1.3.30</version>
    </dependency>
</dependencies>

第三章:详细实现步骤(带完整代码)

3.1 word转pdf:word的“成熟仪式”

创建word处理服务

import org.apache.poi.xwpf.usermodel.*;
import org.springframework.stereotype.service;
import org.apache.pdfbox.pdmodel.*;
import org.apache.pdfbox.pdmodel.font.pdtype1font;
import com.lowagie.text.*;
import com.lowagie.text.pdf.pdfwriter;
import java.io.*;

@service
public class wordtopdfservice {
    
    /**
     * 方法1:使用apache poi + openpdf(适合.doc和.docx)
     * 这是我们的“豪华版”转换,带格式的
     */
    public void convertwordtopdf(inputstream wordstream, outputstream pdfstream) 
            throws exception {
        
        // 1. 读取word文档(就像给word做体检)
        xwpfdocument document = new xwpfdocument(wordstream);
        
        // 2. 创建pdf文档(准备新衣服)
        document pdfdocument = new document();
        pdfwriter.getinstance(pdfdocument, pdfstream);
        pdfdocument.open();
        
        // 3. 逐段处理(把word的每一句话翻译成pdf能听懂的语言)
        for (xwpfparagraph paragraph : document.getparagraphs()) {
            string text = paragraph.gettext();
            if (!text.isempty()) {
                // 设置字体大小(pdf比较挑剔,要明确告诉它)
                font font = new font(font.helvetica, 12);
                pdfdocument.add(new paragraph(text, font));
            }
        }
        
        // 4. 处理表格(如果有的话)
        for (xwpftable table : document.gettables()) {
            // 这里可以添加表格处理逻辑
            // 为了简化,我们先跳过复杂的表格转换
        }
        
        // 5. 完成转换(礼成!)
        pdfdocument.close();
        document.close();
    }
    
    /**
     * 方法2:快速转换版(只提取文本,适合简单文档)
     * 这是“经济适用型”转换
     */
    public void convertwordtopdfsimple(file wordfile, file pdffile) 
            throws ioexception {
        xwpfdocument doc = new xwpfdocument(new fileinputstream(wordfile));
        
        try (pddocument pdfdoc = new pddocument()) {
            pdpage page = new pdpage();
            pdfdoc.addpage(page);
            
            try (pdpagecontentstream contentstream = 
                 new pdpagecontentstream(pdfdoc, page)) {
                
                contentstream.begintext();
                contentstream.setfont(pdtype1font.helvetica, 12);
                contentstream.newlineatoffset(50, 700);
                
                // 逐段添加文本
                for (xwpfparagraph para : doc.getparagraphs()) {
                    string text = para.gettext();
                    if (!text.trim().isempty()) {
                        contentstream.showtext(text);
                        contentstream.newlineatoffset(0, -15); // 换行
                    }
                }
                
                contentstream.endtext();
            }
            
            pdfdoc.save(pdffile);
        }
        
        doc.close();
    }
}

创建rest控制器

import org.springframework.beans.factory.annotation.autowired;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.multipartfile;
import java.io.*;

@restcontroller
@requestmapping("/api/document")
public class documentconversioncontroller {
    
    @autowired
    private wordtopdfservice wordtopdfservice;
    
    /**
     * word转pdf的api端点
     * 访问方式:post /api/document/word-to-pdf
     */
    @postmapping("/word-to-pdf")
    public responseentity<byte[]> convertwordtopdf(
            @requestparam("file") multipartfile file) {
        
        try {
            // 1. 检查文件类型(确保不是乱来的文件)
            string filename = file.getoriginalfilename();
            if (filename == null || 
                (!filename.endswith(".docx") && !filename.endswith(".doc"))) {
                return responseentity.badrequest()
                    .body("只能上传.doc或.docx文件!".getbytes());
            }
            
            // 2. 创建临时文件(给word和pdf准备临时婚房)
            file tempwordfile = file.createtempfile("temp", ".docx");
            file temppdffile = file.createtempfile("converted", ".pdf");
            
            // 3. 保存上传的文件
            file.transferto(tempwordfile);
            
            // 4. 执行转换(见证奇迹的时刻!)
            wordtopdfservice.convertwordtopdfsimple(
                tempwordfile, temppdffile);
            
            // 5. 读取生成的pdf
            byte[] pdfbytes = files.readallbytes(temppdffile.topath());
            
            // 6. 设置响应头(告诉浏览器:这是pdf,请用pdf方式打开)
            httpheaders headers = new httpheaders();
            headers.setcontenttype(mediatype.application_pdf);
            headers.setcontentdisposition(
                contentdisposition.attachment()
                    .filename(filename.replace(".docx", ".pdf").replace(".doc", ".pdf"))
                    .build()
            );
            
            // 7. 清理临时文件(婚房不能留着,要环保)
            tempwordfile.delete();
            temppdffile.delete();
            
            return new responseentity<>(pdfbytes, headers, httpstatus.ok);
            
        } catch (exception e) {
            return responseentity.status(httpstatus.internal_server_error)
                .body(("转换失败:" + e.getmessage()).getbytes());
        }
    }
}

3.2 pdf转word:pdf的“解放运动”

创建pdf转word服务

import org.apache.pdfbox.pdmodel.pddocument;
import org.apache.pdfbox.text.pdftextstripper;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.stereotype.service;
import java.io.*;

@service
public class pdftowordservice {
    
    /**
     * pdf转word - 文本提取版
     * 警告:这就像把煎蛋变回鸡蛋——能变,但样子不一样了
     */
    public void convertpdftoword(file pdffile, file wordfile) throws ioexception {
        
        // 1. 读取pdf(撬开pdf的嘴,让它说话)
        try (pddocument document = pddocument.load(pdffile)) {
            
            // 2. 创建word文档(准备新容器)
            xwpfdocument worddoc = new xwpfdocument();
            
            // 3. 提取pdf文本(让pdf"吐"出文字)
            pdftextstripper stripper = new pdftextstripper();
            string text = stripper.gettext(document);
            
            // 4. 按行分割并添加到word
            string[] lines = text.split("\n");
            for (string line : lines) {
                if (!line.trim().isempty()) {
                    xwpfparagraph paragraph = worddoc.createparagraph();
                    xwpfrun run = paragraph.createrun();
                    run.settext(line);
                    run.setfontsize(12);
                }
            }
            
            // 5. 保存word文档(完成转换)
            try (fileoutputstream out = new fileoutputstream(wordfile)) {
                worddoc.write(out);
            }
            
            worddoc.close();
        }
    }
    
    /**
     * 高级版:带基本格式保留
     * 注意:pdf转word是"世界难题",不要期待完美
     */
    public void convertpdftowordadvanced(inputstream pdfstream, 
                                         outputstream wordstream) 
            throws ioexception {
        
        try (pddocument pdfdoc = pddocument.load(pdfstream);
             xwpfdocument worddoc = new xwpfdocument()) {
            
            pdftextstripper stripper = new pdftextstripper();
            
            // 设置提取参数
            stripper.setsortbyposition(true); // 按位置排序
            stripper.setstartpage(1); // 从第1页开始
            stripper.setendpage(pdfdoc.getnumberofpages()); // 到最后一页
            
            string text = stripper.gettext(pdfdoc);
            
            // 处理文本,尝试保留一些结构
            string[] paragraphs = text.split("\n\n"); // 假设空行是段落分隔
            
            for (string paratext : paragraphs) {
                if (paratext.trim().length() > 0) {
                    xwpfparagraph paragraph = worddoc.createparagraph();
                    
                    // 设置段落格式
                    paragraph.setalignment(paragraphalignment.left);
                    
                    // 添加文本
                    xwpfrun run = paragraph.createrun();
                    run.settext(paratext);
                    run.setfontfamily("宋体");
                    run.setfontsize(12);
                    
                    // 添加空行作为段落间隔
                    worddoc.createparagraph();
                }
            }
            
            worddoc.write(wordstream);
        }
    }
}

添加pdf转word的api端点

// 在documentconversioncontroller中添加
@postmapping("/pdf-to-word")
public responseentity<byte[]> convertpdftoword(
        @requestparam("file") multipartfile file) {
    
    try {
        // 1. 检查文件类型
        string filename = file.getoriginalfilename();
        if (filename == null || !filename.endswith(".pdf")) {
            return responseentity.badrequest()
                .body("只能上传.pdf文件!".getbytes());
        }
        
        // 2. 创建临时文件
        file temppdffile = file.createtempfile("temp", ".pdf");
        file tempwordfile = file.createtempfile("converted", ".docx");
        
        // 3. 保存上传的文件
        file.transferto(temppdffile);
        
        // 4. 执行转换(让pdf"变身")
        pdftowordservice pdftowordservice = new pdftowordservice();
        pdftowordservice.convertpdftoword(temppdffile, tempwordfile);
        
        // 5. 读取生成的word
        byte[] wordbytes = files.readallbytes(tempwordfile.topath());
        
        // 6. 设置响应头
        httpheaders headers = new httpheaders();
        headers.setcontenttype(mediatype.application_octet_stream);
        headers.setcontentdisposition(
            contentdisposition.attachment()
                .filename(filename.replace(".pdf", ".docx"))
                .build()
        );
        
        // 7. 清理临时文件
        temppdffile.delete();
        tempwordfile.delete();
        
        return new responseentity<>(wordbytes, headers, httpstatus.ok);
        
    } catch (exception e) {
        return responseentity.status(httpstatus.internal_server_error)
            .body(("转换失败:" + e.getmessage()).getbytes());
    }
}

3.3 创建前端页面(html + javascript)

<!doctype html>
<html>
<head>
    <title>文档转换器 - word和pdf的相亲平台</title>
    <style>
        body {
            font-family: 'comic sans ms', cursive, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
            background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
        }
        
        .container {
            background: white;
            padding: 30px;
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.1);
        }
        
        h1 {
            color: #2c3e50;
            text-align: center;
            margin-bottom: 30px;
        }
        
        .converter-box {
            border: 2px dashed #3498db;
            padding: 20px;
            border-radius: 10px;
            margin: 20px 0;
            text-align: center;
            transition: all 0.3s;
        }
        
        .converter-box:hover {
            border-color: #e74c3c;
            background: #f9f9f9;
        }
        
        button {
            background: #3498db;
            color: white;
            border: none;
            padding: 12px 24px;
            border-radius: 25px;
            cursor: pointer;
            font-size: 16px;
            margin: 10px;
            transition: all 0.3s;
        }
        
        button:hover {
            background: #2980b9;
            transform: translatey(-2px);
        }
        
        #result {
            margin-top: 20px;
            padding: 15px;
            background: #ecf0f1;
            border-radius: 5px;
            display: none;
        }
        
        .tips {
            background: #fff3cd;
            border-left: 4px solid #ffc107;
            padding: 15px;
            margin: 20px 0;
            border-radius: 0 5px 5px 0;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>📄 word ↔ pdf 转换器 📄</h1>
        <p>让word和pdf愉快地"谈恋爱"!选择你想进行的转换:</p>
        
        <div class="tips">
            <strong>温馨提示:</strong>

            1. word转pdf:婚礼很完美,格式基本保留

            2. pdf转word:离婚再结婚,可能损失一些"财产"(格式)

            3. 文件大小限制:10mb以内
        </div>
        
        <!-- word转pdf区域 -->
        <div class="converter-box">
            <h2>word → pdf 转换</h2>
            <p>让活泼的word变成稳重的pdf(推荐使用)</p>
            <input type="file" id="wordfile" accept=".doc,.docx">
            <button onclick="convertwordtopdf()">开始转换!</button>
        </div>
        
        <!-- pdf转word区域 -->
        <div class="converter-box">
            <h2>pdf → word 转换</h2>
            <p>尝试让高冷的pdf变得可编辑(结果可能"惊喜")</p>
            <input type="file" id="pdffile" accept=".pdf">
            <button onclick="convertpdftoword()">勇敢尝试!</button>
        </div>
        
        <!-- 结果显示区域 -->
        <div id="result">
            <h3>转换结果</h3>
            <p id="resultmessage"></p>
            <a id="downloadlink" style="display:none;">
                <button>下载转换后的文件</button>
            </a>
        </div>
    </div>
    
    <script>
        // word转pdf函数
        async function convertwordtopdf() {
            const fileinput = document.getelementbyid('wordfile');
            const file = fileinput.files[0];
            
            if (!file) {
                alert('请先选择一个word文件!');
                return;
            }
            
            const formdata = new formdata();
            formdata.append('file', file);
            
            try {
                const response = await fetch('/api/document/word-to-pdf', {
                    method: 'post',
                    body: formdata
                });
                
                if (response.ok) {
                    const blob = await response.blob();
                    const url = window.url.createobjecturl(blob);
                    
                    document.getelementbyid('result').style.display = 'block';
                    document.getelementbyid('resultmessage').textcontent = 
                        '转换成功!word已成功"进化"为pdf!';
                    
                    const downloadlink = document.getelementbyid('downloadlink');
                    downloadlink.href = url;
                    downloadlink.download = file.name.replace(/\.(docx|doc)$/, '.pdf');
                    downloadlink.style.display = 'block';
                } else {
                    throw new error('转换失败');
                }
            } catch (error) {
                document.getelementbyid('result').style.display = 'block';
                document.getelementbyid('resultmessage').textcontent = 
                    '转换失败:' + error.message;
            }
        }
        
        // pdf转word函数
        async function convertpdftoword() {
            const fileinput = document.getelementbyid('pdffile');
            const file = fileinput.files[0];
            
            if (!file) {
                alert('请先选择一个pdf文件!');
                return;
            }
            
            const formdata = new formdata();
            formdata.append('file', file);
            
            try {
                const response = await fetch('/api/document/pdf-to-word', {
                    method: 'post',
                    body: formdata
                });
                
                if (response.ok) {
                    const blob = await response.blob();
                    const url = window.url.createobjecturl(blob);
                    
                    document.getelementbyid('result').style.display = 'block';
                    document.getelementbyid('resultmessage').textcontent = 
                        'pdf成功"解放"为word!部分格式可能丢失,请理解。';
                    
                    const downloadlink = document.getelementbyid('downloadlink');
                    downloadlink.href = url;
                    downloadlink.download = file.name.replace('.pdf', '.docx');
                    downloadlink.style.display = 'block';
                } else {
                    throw new error('转换失败');
                }
            } catch (error) {
                document.getelementbyid('result').style.display = 'block';
                document.getelementbyid('resultmessage').textcontent = 
                    '转换失败:' + error.message + '。pdf可能太"固执"了!';
            }
        }
    </script>
</body>
</html>

3.4 添加application主类

import org.springframework.boot.springapplication;
import org.springframework.boot.autoconfigure.springbootapplication;
import org.springframework.context.annotation.bean;
import org.springframework.web.multipart.commons.commonsmultipartresolver;

@springbootapplication
public class documentconverterapplication {
    
    public static void main(string[] args) {
        springapplication.run(documentconverterapplication.class, args);
        system.out.println("======================================");
        system.out.println("文档转换服务启动成功!");
        system.out.println("访问地址:http://localhost:8080");
        system.out.println("word和pdf可以开始'谈恋爱'了!");
        system.out.println("======================================");
    }
    
    @bean(name = "multipartresolver")
    public commonsmultipartresolver multipartresolver() {
        commonsmultipartresolver resolver = new commonsmultipartresolver();
        resolver.setmaxuploadsize(10485760); // 10mb限制
        resolver.setdefaultencoding("utf-8");
        return resolver;
    }
}

3.5 添加配置文件(application.yml)

spring:
  servlet:
    multipart:
      max-file-size: 10mb
      max-request-size: 10mb
  application:
    name: document-converter

server:
  port: 8080
  servlet:
    context-path: /

# 日志配置,方便调试
logging:
  level:
    org.springframework.web: info
    com.example.documentconverter: debug
  file:
    name: logs/document-converter.log

第四章:项目优化和高级功能

4.1 添加批量转换功能

@service
public class batchconversionservice {
    
    /**
     * 批量转换 - 适合大量文档处理
     * 比如:把整个部门的word报告都转成pdf
     */
    public void batchwordtopdf(list<file> wordfiles, file outputdir) {
        wordfiles.parallelstream().foreach(wordfile -> {
            try {
                file pdffile = new file(outputdir, 
                    wordfile.getname().replacefirst("\\.[^.]+$", "") + ".pdf");
                // 调用转换服务
                // wordtopdfservice.convertwordtopdfsimple(wordfile, pdffile);
                system.out.println("转换完成: " + wordfile.getname());
            } catch (exception e) {
                system.err.println("转换失败: " + wordfile.getname() + " - " + e.getmessage());
            }
        });
    }
}

4.2 添加转换进度跟踪

@component
public class conversionprogresstracker {
    
    private map<string, conversionstatus> statusmap = new concurrenthashmap<>();
    
    public enum conversionstatus {
        pending, processing, completed, failed
    }
    
    public void startconversion(string taskid, string filename) {
        statusmap.put(taskid, conversionstatus.processing);
    }
    
    public void updateprogress(string taskid, int progress) {
        // 更新进度
    }
    
    public conversionstatus getstatus(string taskid) {
        return statusmap.getordefault(taskid, conversionstatus.pending);
    }
}

4.3 添加水印功能

@service
public class watermarkservice {
    
    /**
     * 给pdf添加水印
     */
    public void addwatermarktopdf(file pdffile, string watermarktext) 
            throws ioexception {
        
        try (pddocument document = pddocument.load(pdffile)) {
            for (pdpage page : document.getpages()) {
                try (pdpagecontentstream contentstream = 
                     new pdpagecontentstream(document, page, 
                             pdpagecontentstream.appendmode.append, true)) {
                    
                    // 设置水印样式
                    contentstream.setfont(pdtype1font.helvetica_oblique, 60);
                    contentstream.setnonstrokingcolor(200, 200, 200); // 浅灰色
                    
                    // 旋转45度
                    contentstream.begintext();
                    contentstream.settextrotation(math.toradians(45), 
                        page.getmediabox().getwidth() / 2, 
                        page.getmediabox().getheight() / 2);
                    
                    contentstream.showtext(watermarktext);
                    contentstream.endtext();
                }
            }
            
            document.save(pdffile);
        }
    }
}

第五章:总结与心得

5.1 转换效果对比

word转pdf

  • 成功率高,就像把新鲜水果做成果酱——能很好地保存原味
  • 格式基本保留,布局不乱
  • 推荐使用apache poi + openpdf组合

pdf转word

  • 像把炒熟的鸡蛋变回生鸡蛋——技术上有难度
  • 复杂格式(表格、特殊排版)容易丢失
  • 扫描版pdf需要ocr,这是另一个故事了

5.2 实战建议

选择合适的工具库

  • 简单需求:apache poi + pdfbox
  • 复杂需求:考虑aspose或商业库(但要花钱)
  • 云端方案:直接用microsoft graph api或google docs api

性能优化建议

  • 大文件分块处理
  • 使用内存映射文件
  • 考虑异步处理 + websocket推送进度

错误处理要点

  • 一定要关闭文档流(否则内存泄漏)
  • 添加文件类型验证
  • 设置合理的超时时间

安全注意事项

  • 限制上传文件大小
  • 检查文件内容(防止恶意文件)
  • 临时文件及时清理

5.3 结语

通过这个项目,我们成功地为word和pdf搭建了一个"相亲平台":

  • word转pdf就像一场浪漫的婚礼:word穿上pdf的婚纱,承诺"从今以后,我的格式永不变心"。
  • pdf转word则像一场冒险:pdf尝试脱下严肃的外套,说"让我也试试自由的感觉"。

以上就是springboot实现word和pdf互相转换的操作详解的详细内容,更多关于springboot word和pdf互转的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com