SpringBoot整合office转换与预览

  • Post author:
  • Post category:其他




一、介绍



1、简介

有时候我们需要在程序中使用到office的转换和预览功能,本文就针对这个需求记录了两种较为简单的office转换和功能:aspose和jodconverter。当然还有其他开源第三方(

kkfileview

)



2、aspose简介

Aspose.Total是Aspose公司旗下的最全的一套office文档管理方案,主要提供.net跟java两个开发语言的控件套包,通过它,可以有计划地操纵一些商业中最流行的

文件格式

:Word, Excel, PowerPoint, Project,等office文档以及PDF文档。

但是不足的是aspose包是收费的,并且单独收费,网上有很多资料和程序可以参考下载,这里提供一个下载地址

aspose相关jar包下载



3、jodconverter简介

JODConverter是 Java OpenDocument 转换器,可在不同办公格式之间转换文档。它利用Apache OpenOffice或LibreOffice,它们为当今可用的 OpenDocument 和 Microsoft Office 格式提供可以说是最好的免费导入/导出过滤器。

JODConverter自动执行 OpenOffice/LibreOffice 支持的所有转换

。但要求在本机率先安装好相应的程序,目标是完成

office文档->pdf

但是其优点是免费,可以在win/linux上使用,这里更加推荐libreoffice



二、springboot整合aspose实战



1、前期依赖准备



1.1 介绍

下载好相关依赖包后,就需要在springboot项目里引入相关jar包还有

License.xml

文件,

License.xml

文件就放在

reseources

目录下,这里有两种方式引入jar包,项目直接引入以及在maven添加本地包,其中

License.xml

文件内容如下,word,excel转pdf可共用一个license.xml

<License>
    <Data>
        <Products>
            <Product>Aspose.Total for Java</Product>
            <Product>Aspose.Excel for Java</Product>
        </Products>
        <EditionType>Enterprise</EditionType>
        <SubscriptionExpiry>20991231</SubscriptionExpiry>
        <LicenseExpiry>20991231</LicenseExpiry>
        <SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
    </Data>
    <Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>
</License>



1.2 项目直接引入jar包

其他三个包同理

在这里插入图片描述

<!--添加本地的jacob.jar包-->
<dependency>
    <groupId>com.aspose</groupId> <!--自定义-->
    <artifactId>aspose-slides</artifactId> <!--自定义-->
    <version>15.9.0</version>  <!--自定义-->
    <scope>system</scope>
    <systemPath>${basedir}/src/main/resources/lib/aspose.slides-15.9.0.jar</systemPath>
    <!--如果把lib放在和pom.xml同级目录下-->
    <!--<systemPath>${pom.basedir}/lib/aspose.slides-15.9.0.jar</systemPath>-->
</dependency>

最后在pom.xml引入

<plugins>
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <includeSystemScope>true</includeSystemScope>
        </configuration>
    </plugin>

</plugins>



1.3 maven添加本地包

其他三个包同理,直接在命令行添加安装

mvn install:install-file  -Dfile=D:\share\aspose\jar\aspose-words-14.9.0-jdk16.jar -DgroupId=com.aspose -DartifactId=aspose-words -Dversion=14.9.0 -Dpackaging=jar

其次在pom.xml文件上直接使用即可

<dependency>
    <groupId>com.aspose</groupId>
    <artifactId>aspose-words</artifactId>
    <version>14.9.0</version>
</dependency>



2、office转pdf实现

这里主要介绍word/ppt/excel转pdf以及其在线预览,另外还有pdf转png/jpg

文件上传可以参考

SpringBoot文件上传与校验



2.1 word转pdf

这里还可以控制生成水印

import com.aspose.words.*;
import com.aspose.words.Shape;

import java.awt.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * word转pdf
 */
public class WordToPdfUtils {

    /**
     *  word转pdf
     * @param inPath word文件路径
     * @param outPath 输出路径
     */
    public static boolean doc2pdf(String inPath, String outPath) {
        String str ="sdojfiosdjoifjiosiojsdf";
        FileOutputStream os =null;
        try {
            // 新建一个空白pdf文档
            File file = new File(outPath);
            os = new FileOutputStream(file);
            // Address是将要被转化的word文档
            Document doc = new Document(inPath);
            //添加水印
            insertWatermarkText(doc,str);
            //保存pdf文件
            //全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
            doc.save(os, SaveFormat.PDF);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }finally{
            if(os!=null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return true;
        }
    }


    /**
     * @Description: PDF生成水印
     */
    private static void insertWatermarkText(Document doc, String watermarkText) throws Exception
    {
        if (!watermarkText.equals("")&&null!=watermarkText){
            Shape watermark = new Shape(doc, ShapeType.TEXT_PLAIN_TEXT);
            //水印内容
            watermark.getTextPath().setText(watermarkText);
            //水印字体
            watermark.getTextPath().setFontFamily("宋体");
            //水印宽度
            watermark.setWidth(400);
            //水印高度
            watermark.setHeight(100);
            //旋转水印
            watermark.setRotation(-30);
            //水印颜色
            watermark.getFill().setColor(Color.lightGray);
            watermark.setStrokeColor(Color.lightGray);
            watermark.setRelativeHorizontalPosition(RelativeHorizontalPosition.PAGE);
            watermark.setRelativeVerticalPosition(RelativeVerticalPosition.PAGE);
            watermark.setWrapType(WrapType.NONE);
            watermark.setVerticalAlignment(VerticalAlignment.CENTER);
            watermark.setHorizontalAlignment(HorizontalAlignment.CENTER);
            Paragraph watermarkPara = new Paragraph(doc);
            watermarkPara.appendChild(watermark);
            for (Section sect : doc.getSections())
            {
                insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_PRIMARY);
                insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_FIRST);
                insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_EVEN);
            }
        }
    }
    private static void insertWatermarkIntoHeader(Paragraph watermarkPara, Section sect, int headerType) throws Exception
    {
        HeaderFooter header = sect.getHeadersFooters().getByHeaderFooterType(headerType);
        if (header == null)
        {
            header = new HeaderFooter(sect.getDocument(), headerType);
            sect.getHeadersFooters().add(header);
        }
        header.appendChild(watermarkPara.deepClone(true));
    }

    public static void main(String[] args) {
        doc2pdf("D:\\share\\1234.doc","D:\\share\\1234.pdf");
    }

}



2.2 Excel转pdf

import com.aspose.cells.License;
import com.aspose.cells.PdfSaveOptions;
import com.aspose.cells.SaveFormat;
import com.aspose.cells.Workbook;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * excel转pdf帮助类
 */
public class ExcelToPdfUtils {

    /**
     * excel转pdf方法
     *
     * @param Address 原路径excel
     * @param putPath 转换pdf后的路径
     */
    public static void excel2pdf(String Address, String putPath) throws IOException {
        // 验证License 若不验证则转化出的pdf文档会有水印产生
        if (!getLicense()) {
            return;
        }

        FileOutputStream fileOS=null;
        try {

            // 原始excel路径
            Workbook wb = new Workbook(Address);

            fileOS = new FileOutputStream(putPath);

            int[] autoDrawSheets={3};
            //当excel中对应的sheet页宽度太大时,在PDF中会拆断并分页。此处等比缩放。
            autoDraw(wb,autoDrawSheets);

            int[] showSheets={0};
            //隐藏workbook中不需要的sheet页。
            printSheetPage(wb,showSheets);

            // 设置一页,即长页
            // PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
            // pdfSaveOptions.setOnePagePerSheet(true);
            // wb.save(fileOS, pdfSaveOptions);

            wb.save(fileOS,SaveFormat.PDF);
            fileOS.flush();
            fileOS.close();
            System.out.println("转换完毕");
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            fileOS.close();
        }
    }

    /**
     * 设置打印的sheet 自动拉伸比例
     * @param wb
     * @param page 自动拉伸的页的sheet数组
     */
    public static void autoDraw(Workbook wb,int[] page){
        if(null!=page&&page.length>0){
            for (int i = 0; i < page.length; i++) {
                wb.getWorksheets().get(i).getHorizontalPageBreaks().clear();
                wb.getWorksheets().get(i).getVerticalPageBreaks().clear();
            }
        }
    }

    /**
     * 隐藏workbook中不需要的sheet页。
     * @param wb
     * @param page 显示页的sheet数组
     */
    public static void printSheetPage(Workbook wb,int[] page){
        for (int i= 1; i < wb.getWorksheets().getCount(); i++)  {
            wb.getWorksheets().get(i).setVisible(false);
        }
        if(null==page||page.length==0){
            wb.getWorksheets().get(0).setVisible(true);
        }else{
            for (int i = 0; i < page.length; i++) {
                wb.getWorksheets().get(i).setVisible(true);
            }
        }
    }


    public static boolean getLicense() {
        boolean result = false;
        try {
            InputStream is = ExcelToPdfUtils.class
                            .getClassLoader()
                            .getResourceAsStream("license.xml");
            // license.xml这个文件你放在静态文件资源目录下就行了
            License aposeLic = new License();
            aposeLic.setLicense(is);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static void main(String[] args) throws IOException {
        excel2pdf("D:\\share\\excel.xlsx","D:\\share\\excel.pdf");
    }
}



2.3 ppt转pdf

import com.aspose.slides.License;
import com.aspose.slides.Presentation;
import com.aspose.slides.SaveFormat;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

/**
 * ppt 转pdf  帮助类
 */
public class PptToPdfUtils {



    /**
     * 获取license
     *
     * @return
     */
    public static boolean getLicense() {
        boolean result = false;
        try {

            // license路径
            InputStream license = PptToPdfUtils.class.getClassLoader().getResourceAsStream("license.xml");
            License aposeLic = new License();
            aposeLic.setLicense(license);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


    /**
     * ppt 转pdf 方法
     * @param Address ppt原路径
     * @param outPath pdf转出路径
     */
    public static void ppt2pdf(String Address,String outPath) {
        // 验证License
        if (!getLicense()) {
            return ;
        }
        try {
            // 输出pdf路径
            File file = new File(outPath);
            //输入ppt路径
            Presentation pres = new Presentation(Address);
            FileOutputStream fileOS = new FileOutputStream(file);
            pres.save(fileOS, SaveFormat.Pdf);
            fileOS.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        ppt2pdf("D:\\share\\ppt.pptx","D:\\share\\ppt.pdf");
    }
}



2.4 pdf转图片

首先需要在pom.xml中引入相关依赖

<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.21</version>
</dependency>

工具类代码

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPageTree;
import org.apache.pdfbox.rendering.PDFRenderer;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * pdf 转图片 帮助类
 */
public class PdftoImageUtils {

    /**
     *  pdf 转图片方法
     * @param address pdf原文件地址
     * @param toImagepath  转换后图片存放地址
     * @return   图片地址集合
     * @throws Exception
     */
    public static List<String> pdfToImageFile(String address, String toImagepath) throws Exception {
        PDDocument doc = null;
        ByteArrayOutputStream os = null;
        InputStream stream = null;
        OutputStream out = null;
        ArrayList<String> strings = new ArrayList<>();
        try {
            // pdf路径
            stream = new FileInputStream(address);
            // 加载解析PDF文件
            doc = PDDocument.load(stream);
            PDFRenderer pdfRenderer = new PDFRenderer(doc);
            PDPageTree pages = doc.getPages();
            int pageCount = pages.getCount();
            for (int i = 0; i < pageCount; i++) {
                BufferedImage bim = pdfRenderer.renderImageWithDPI(i, 200);
                os = new ByteArrayOutputStream();
                ImageIO.write(bim, "jpg", os);
                byte[] dataList = os.toByteArray();
                //获取当前时间  保存图片规则
                Date date = new Date();
                //可以方便地修改日期格式
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
                String format = dateFormat.format(date).replace(":","/");
                //随机数
                int anInt = new Random().nextInt(1000);
                String imageAddress=toImagepath+"/"+format+"/hello_" + anInt + ".jpg";
                strings.add(imageAddress);
                // jpg文件转出路径
                File file = new File(imageAddress);
                if (!file.getParentFile().exists()) {
                    // 不存在则创建父目录及子文件
                    file.getParentFile().mkdirs();
                    file.createNewFile();
                }
                out = new FileOutputStream(file);
                out.write(dataList);
            }
            return strings;
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (doc != null) {
                doc.close();
            }
            if (os != null) {
                os.close();
            }
            if (stream != null) {
                stream.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        pdfToImageFile("D:\\share\\菜单.pdf","D:\\share\\菜单.jpg");
    }
}



2.5 pdf添加水印

首先添加依赖

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

工具包

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;

import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 给pdf添加水印工具
 */
public class PdfWithWatermarkUtils {


    /**
     * pdf添加水印
     * @param inputFile 需要添加水印的文件
     * @param outputFile 添加完水印的文件存放路径
     * @param cover 是否覆盖
     * @return
     */
    public static boolean addwaterMark(String inputFile, String outputFile,boolean cover) {

        String waterMarkName = "测试水印";
        //水印字体透明度
        float opacity = 0.3f;
        //水印字体大小
        int fontsize = 30;
        //水印倾斜角度(0-360)
        int angle = 30;
        //数值越大每页竖向水印越少
        int heightdensity = 20;
        //数值越大每页横向水印越少
        int widthdensity = 4;


        if (!cover){
            File file=new File(outputFile);
            if (file.exists()){
                return true;
            }
        }
        File file=new File(inputFile);
        if (!file.exists()){
            return false;
        }

        PdfReader reader = null;
        PdfStamper stamper = null;
        try {
            int interval = -5;
            reader = new PdfReader(inputFile);
            stamper = new PdfStamper(reader, new FileOutputStream(outputFile));
            BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
            Rectangle pageRect = null;
            PdfGState gs = new PdfGState();
            //这里是透明度设置
            gs.setFillOpacity(opacity);
            //这里是条纹不透明度
            gs.setStrokeOpacity(0.2f);
            int total = reader.getNumberOfPages() + 1;
            System.out.println("Pdf页数:" + reader.getNumberOfPages());
            JLabel label = new JLabel();
            FontMetrics metrics;
            int textH = 0;
            int textW = 0;
            label.setText(waterMarkName);
            metrics = label.getFontMetrics(label.getFont());
            //字符串的高,   只和字体有关
            textH = metrics.getHeight();
            //字符串的宽
            textW = metrics.stringWidth(label.getText());
            PdfContentByte under;
            //这个循环是确保每一张PDF都加上水印
            for (int i = 1; i < total; i++) {
                pageRect = reader.getPageSizeWithRotation(i);
                under = stamper.getOverContent(i);  //在内容上方添加水印
                //under = stamper.getUnderContent(i);  //在内容下方添加水印
                under.saveState();
                under.setGState(gs);
                under.beginText();
                //under.setColorFill(BaseColor.PINK);  //添加文字颜色  不能动态改变 放弃使用
                under.setFontAndSize(base, fontsize); //这里是水印字体大小
                for (int height = textH; height < pageRect.getHeight() * 2; height = height + textH * heightdensity) {
                    for (int width = textW; width < pageRect.getWidth() * 1.5 + textW; width = width + textW * widthdensity) {
                        // rotation:倾斜角度
                        under.showTextAligned(Element.ALIGN_LEFT, waterMarkName, width - textW, height - textH, angle);
                    }
                }
                //添加水印文字
                under.endText();
            }
            System.out.println("添加水印成功!");
            return true;
        } catch (IOException e) {
            System.out.println("添加水印失败!错误信息为: " + e);
            e.printStackTrace();
            return false;
        } catch (DocumentException e) {
            System.out.println("添加水印失败!错误信息为: " + e);
            e.printStackTrace();
            return false;
        } finally {
            //关闭流
            if (stamper != null) {
                try {
                    stamper.close();
                } catch (DocumentException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                reader.close();
            }
        }
    }
}



3、office在线预览(简单版)

引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>


application.yml

配置

server:
  port: 8080

upload:
  path: D:\\share\\

工具类

import javax.servlet.http.HttpServletResponse;
import java.io.*;

public class FileUtil {

    /**
     * @Description 查看对应的.pdf文件是否存在
     * @Date 2021/3/12
     **/
    public static boolean checkFileExist(String filePath) {
        File file = new File(filePath);
        // 文件是否存在
        if (file.exists()) {
            return true;
        }
        return false;
    }


    public static void deleteFile(String filePath) {
        File file = new File(filePath);
        if (file.exists()) {//文件是否存在
            file.delete();//删除文件
        }
    }


    /**
     * @Author WXK
     * @Description 返回预览pdf流
     * @Date 2021/3/11
     **/
    public static void previewFile(String filePath, HttpServletResponse res) throws IOException {
        // 发送给客户端的数据
        OutputStream outputStream = res.getOutputStream();
        try {
            byte[] buff = new byte[1024];
            BufferedInputStream bis = null;
            // 读取filename
            bis = new BufferedInputStream(new FileInputStream(filePath));
            int i = bis.read(buff);
            while (i != -1) {
                outputStream.write(buff, 0, buff.length);
                outputStream.flush();
                i = bis.read(buff);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            outputStream.close();
        }
    }
}

controller层,启动后访问接口即可成功在线预览,还可以直接下载

import com.example.mx80.utils.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

@RestController
public class FileController {

    @Value("${upload.path}")
    private  String path;


    @GetMapping("preview")
    public void previewFile(String fileName, HttpServletResponse response)  {
        try{
            //response.setContentType("text/html;charset=UTF-8");
            String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
            if("PDF".equalsIgnoreCase(suffix)){
                String newFileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
                // 设置扩展头,当Content-Type 的类型为要下载的类型时 , 这个信息头会告诉浏览器这个文件的名字和类型。
                //response.setHeader("Content-Disposition", "attachment;filename=" + newFileName);
                if(FileUtil.checkFileExist(path + fileName)){
                    FileUtil.previewFile(path + fileName,response);
                }
                return;
            }

            String oldPath = path + fileName;
            String filePath = path + fileName.substring(0,fileName.lastIndexOf(".")) + ".pdf";
            if( FileUtil.checkFileExist(filePath)){
                FileUtil.previewFile(filePath,response);
            }else {
                if("XLSX".equalsIgnoreCase(suffix) || "XLS".equalsIgnoreCase(suffix)){
                    ExcelToPdfUtils.excel2pdf(oldPath,filePath);
                }else if("PPT".equalsIgnoreCase(suffix)||"pptx".equalsIgnoreCase(suffix)){
                    PptToPdfUtils.ppt2pdf(oldPath,filePath);
                }else {
                    //DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF
                    WordToPdfUtils.doc2pdf(oldPath,filePath);
                }


                if(FileUtil.checkFileExist(filePath)){
                    FileUtil.previewFile(filePath,response);
                }
                // 转换完毕删除文件
                //FileUtil.deleteFile(filePath);
                System.out.println("成功");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @GetMapping("previewPdf")
    public void previewPdf(String fileName, HttpServletResponse response)  {
        try{
            //response.setContentType("text/html;charset=UTF-8");
            String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);

            if("PDF".equalsIgnoreCase(suffix)){
                String realFileName = fileName.substring(0,fileName.lastIndexOf("."));
                String inPath = path + fileName;
                String outPath = path + realFileName + "(水印).pdf";
                String newFileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
                // 设置扩展头,当Content-Type 的类型为要下载的类型时 , 这个信息头会告诉浏览器这个文件的名字和类型。
                //response.setHeader("Content-Disposition", "attachment;filename=" + newFileName);
                PdfWithWatermarkUtils.addwaterMark(inPath,outPath,true);
                FileUtil.previewFile(outPath,response);

                // 转换完毕删除文件
                //FileUtil.deleteFile(outPath);
            }else {
                System.err.println("文件不是pdf");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}




三、SpringBoot集成jodconverter实战



1、前期依赖准备

首先下载好OpenOffice或LibreOffice,并在

pom.xml

引入相关依赖

<!--转换工具-->
<dependency>
    <groupId>org.jodconverter</groupId>
    <artifactId>jodconverter-spring-boot-starter</artifactId>
    <version>4.4.2</version>
</dependency>
<dependency>
    <groupId>org.jodconverter</groupId>
    <artifactId>jodconverter-local</artifactId>
    <version>4.4.2</version>
</dependency>
<dependency>
    <groupId>org.jodconverter</groupId>
    <artifactId>jodconverter-core</artifactId>
    <version>4.4.2</version>
</dependency>

其次在

application.yml

设置相关参数

# word 转 pdf 相关配置
jodconverter:
  local:
    # 嵌入式调用
    enabled: true
    # libreOffice根目录
    #    office-home: /opt/libreoffice7.2
    officeHome: C:\Program Files\LibreOffice
    # 任务执行的超时时间 默认120000 毫秒
    taskExecutionTimeout: 12000
    # 任务队列的超时时间 默认30000 毫秒
    taskQueueTimeout: 120000
    # 端口(线程)
    portNumbers: [ 2002, 2003, 2004, 2005 ]
    # 一个进程的超时时间 默认120000 毫秒
    processTimeout: 120000


spring:
  # 文件上传限制大小
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 10MB



2、office转pdf实战

这里是我的controller类,可以简单参考,这里只做了文件上传和下载,预览和下载其实一个道理,可以参考上面

@RestController
public class jodController {

    @Autowired
    JodService jodService;

    @PostMapping(value = "/upload", consumes = "multipart/*", headers = "content-type=multipart/form-data")
    public ResponseEntity<String> uploadPolicy(MultipartFile file) {
        // 通过request拿到上传文件的用户的用户名
        HttpServletRequest request =
                ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        Principal userPrincipal = request.getUserPrincipal();
        String s = jodService.uploadPolicy(file);
        return ResponseEntity.ok(s);
    }


    @GetMapping("/codpreview")
    public ResponseEntity<InputStreamSource> previewPolicy(HttpServletResponse response, @RequestParam("file") String filePreName) throws  UnsupportedEncodingException {

        File file;
        try {
            file = jodService.downloadFile(filePreName);
        } catch (FileNotFoundException e) {
            return ResponseEntity.notFound().build();
        }
        String fileName = filePreName+ ".pdf";
        // 如果文件存在
        if (file.exists()) {
            FileSystemResource resource = new FileSystemResource(file);
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes(StandardCharsets.UTF_8), "ISO8859-1"));
            return ResponseEntity.ok()
                    // 指定文件的contentType
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .headers(headers)
                    .body(resource);
        } else {
            // 如果文件不存在,返回404响应
            return ResponseEntity.notFound().build();
        }
    }
}

我的service类,包含下载和文件转换,这里我把文件都保存在了

target/classes/static/docs

下面了

@Service
public class JodService {

    public final static String FILE_SUFFIX = ".doc.docx.pdf.xlsx";
    public final static String FILE_PATH = "/static/docs/";

    /**
     * @param file 传入的文件
     * @return policy_id 文件主键,如果为小于0,插入失败;如果大于0,插入成功。
     */
    public String uploadPolicy(MultipartFile file) {
        if (file.isEmpty()) {
            //文件为空
            return "文件为空";
        }
        String fileName = file.getOriginalFilename();
        assert fileName != null;
        String suffix = fileName.substring(fileName.lastIndexOf('.') + 1);
        if (!FILE_SUFFIX.contains(suffix)) {
            //文件未命名
            return "文件未命名";
        }
        //写入文件
        try {
            String filePrefix = new SimpleDateFormat("yyyy-MM-dd-HHmmssS").format(new Date());
            String newFileName = filePrefix + "." + suffix;
            File path = new File(ResourceUtils.getURL("classpath:").getPath());
            if (!path.exists()) {
                path = new File("");
            }
            File upload = new File(path.getAbsolutePath(), FILE_PATH + newFileName);
            if (!upload.exists()) {
                boolean b = upload.mkdirs();
            }
            file.transferTo(upload);
            if (!suffix.contains("pdf")) {
                // 异步转换
                new Thread(() -> {
                    convertPdf(filePrefix, suffix);
                }).start();
            }
            return filePrefix;
        } catch (Exception e) {
            e.printStackTrace();
            // 保存文件失败
            return "文件保存失败";
        }
    }

    @Resource
    DocumentConverter converter;

    /**
    * 需要在启动类上加@EnableAsync才可以生效
    * 文件转换类
    */
    @Async
    public void convertPdf(String filePrefix, String fileType) {
        try {
            File rootPath = new File(ResourceUtils.getURL("classpath:").getPath());
            File sourceFile = new File(rootPath.getAbsolutePath(), FILE_PATH + filePrefix + "." + fileType);
            String sourceFilePath = sourceFile.getAbsolutePath();
            File newFile = new File(sourceFilePath.substring(0, sourceFilePath.lastIndexOf(".")) + ".pdf");
            // convert方法指定源文件对象/输入流
            // to方法指定目标文件对象/输出流(源文件可以不存在,如果不存在则会创建)
            // todo: 目标文件的后缀要和即将转换的文件类型一致,否则会造成文件损坏
            // todo: as方法接受的时DocumentFormat对象,我们可以使用默认注册完的DocumentFormat对象,
            // execute方法是执行转换的方法,方法没有返回值,是同步执行
            converter.convert(sourceFile).to(newFile).as(DefaultDocumentFormatRegistry.PDF).execute();
        } catch (OfficeException | FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 下载pdf
     * @param filePreName
     */
    public File downloadFile(String filePreName) throws FileNotFoundException {
        return new File(
                new File(ResourceUtils.getURL("classpath:").getPath()).getAbsolutePath(),
                FILE_PATH + filePreName + ".pdf");

    }
}


参考文章


https://blog.csdn.net/WXk_wer/article/details/116977449


https://blog.csdn.net/weixin_46031754/article/details/121670267



版权声明:本文为lemon_TT原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。