SpringBoot整合office转换与预览

2023-10-27

一、介绍

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringBoot整合office转换与预览 的相关文章

  • HTML <strong> 标签

    定义和用法 以下元素都是短语元素 虽然这些标签定义的文本大多会呈现出特殊的样式 但实际上 这些标签都拥有确切的语义 我们并不反对使用它们 但是如果您只是为了达到某种视觉效果而使用这些标签的话 我们建议您使用样式表 那么做会达到更加丰富的效果
  • 实现在最新版本的cesium中引用叠加shp文件的类的功能

    因为刚接触cesium不久 对js的编码规范什么的也不是很懂 所以这么简单的问题就搞了好几天 不过总算有所突破了 网上看到这个文章 http blog sina com cn s blog 15e866bbe0102xxd1 html 里面
  • springboot+springcloud相关面试题

    什么是springboot 用来简化spring应用的初始搭建以及开发过程 使用特定的方式来进行配置 properties或yml文件 创建独立的spring引用程序 main方法运行 嵌入的Tomcat 无需部署war文件 简化maven

随机推荐

  • 学习笔记(103):R语言入门基础-数据点类型(type参数)

    立即学习 https edu csdn net course play 24913 285847 utm source blogtoedu type参数 type p 在图形中数据显示为点 type l 在图形中数据显示为线 type b
  • sort排序用法

    Python sorted函数 我们需要对List Dict进行排序 Python提供了两个方法对给定的List L进行排序 方法1 用List的成员函数sort进行排序 在本地进行排序 不返回副本方法2 用built in函数sorted
  • 在矩池云使用Llama2-7B的具体方法

    今天给大家分享如何在矩池云服务器使用 Llama2 7b模型 硬件要求 矩池云已经配置好了 Llama 2 Web UI 环境 显存需要大于 8G 可以选择 A4000 P100 3090 以及更高配置的等显卡 租用机器 在矩池云主机市场
  • 图像对比度,亮度

    很多时候 一张图像被过度曝光 显得很白 或者光线不足显得很暗 这个时候可以通过调节图像的这两个基本属性 亮度与对比度 来获得整体效果的提升 从而获得质量更高的图片 1 算子operator 首先我们给出算子的概念 一般的图像处理算子都是一个
  • 电源学习总结(五)——开关电源基本原理

    前面讲了一些线性稳压的原理和设计的基本方法 事实上 除了一些功率较大或者对精度要求较高的电源设计 使用集成的线性稳压芯片很少出现 翻车 事故 一般只需关注输入输出范围即可 此外 需注意由于集成的开关电源芯片 尤其是贴片封装的 如SOT 22
  • 【CUDA】初步了解PageLocked host memory的mapped memory功能使用

    导言 大家都知道CUDA 中PageLocked memory 相比portable memory 有着多种优势 在有front side bus的系统中 pagelocked memory 所提供的host 与device之间的数据传送速
  • 硬盘突然提示没有初始化_分享一下固态硬盘不认盘的修复方法

    写在开头 固态硬盘比较害怕突然停电 如果里面有重要数据 请勿用此方法尝试修复 即便可以成功 里面的数据也已经被抹除 需要恢复数据的话 还是需要找专业的数据恢复公司来做 切勿自己折腾 进入正题 前段时间淘了一块威刚的SP550 120G SA
  • 常用脚本(九)Unity_Input

    1 输出鼠标位置 在Update方法中 Debug Log Input mouseposition 2 判断鼠标是否点击 返回 True 和 false 每帧都输出 在Update方法中 Debug Log Input anykey 3 I
  • run()方法和start()方法的区别

    run 方法和start 方法的区别 文章目录 run 方法和start 方法的区别 一 start 是什么 二 run 是什么 三 具体代码实例 四 start 和run 方法的区别 参考 一 start 是什么 用 start方法来启动
  • 安全并正确地重启Elasticsearch集群

    文章目录 前言 问题原因其本质 提前准备 准备重启集群 更新集群 前言 elasticsearch本身具有高可用性 可以做到停机不停服务 在重启elasticsearch后可能存在数据丢失 或者是 启动ES后 怎么一直有大量的数据在迁移 问
  • 快速创建一个spring boot项目

    写了两年还在创建spring boot 项目 最近想自己尝试开发一个项目 所以随便记录一下吧 平常 工作都是现成的项目开发 在项目上加新功能之类的 除了工作平常回去也没琢磨 现在想多思考 为了国庆之后辞职 找工作做一个铺垫 分割线 选择一些
  • linux内核vmlinux生成过程简要分析

    最近工作不太忙 研究了一下Linux内核的编译过程 在此简要记录一下 obj zImage obj compressed vmlinux FORCE call if changed objcopy linux的内核 zImage 的生成依赖
  • 第二天(七)osg::Object* readObjectFile_const std::string& filename_const ReaderWriter::Options* options

    目前流程是 osgViewer viewBase frame viewerInit 创建帧事件 并将漫游器与事件和视口相关联 gt osgViewer Viewer ViewerInit gt osgViewer View Init gt
  • 电脑老是安装一些来路不明的软件(如何解决)?

    目录 先解决自身可能出现的问题 上四大方法 先解决自身可能出现的问题 1 自行百度下载软件 没有到官网那去下载 进入一些假官网下载软件会附带一些流氓软件 看好官网地址再下载或者用安全软件那去下载 2 电脑的浏览器被劫持了 浏览器会有小广告
  • 智能指针与引用计数详解(二)

    在智能指针与引用计数详解 一 当中讲了智能指针还有改进的地方 下面具体问题具体分析 一 智能指针的赋值方法改进 上一章的赋值方法中只要是赋值都是右操作数引用计数加一 左操作数引用计数减一 没有考虑过引用计数对象自赋值的情况 比如按照上一章代
  • Windows键盘对应苹果的Option键

    用mini mac的用户 如果用的是windows的键盘 那么开发时功能键或多或少会有一些不适应 特别是在xCode4中 我就一直没有找到option对应的windows键 苹果有介绍 http support apple com kb H
  • Matlab学习——求解微分方程(组)

    介绍 1 在 Matlab 中 用大写字母 D 表示导数 Dy 表示 y 关于自变量的一阶导数 D2y 表示 y 关于自变量的二阶导数 依此类推 函数 dsolve 用来解决常微分方程 组 的求解问题 调用格式为 X dsolve eqn1
  • 自定义指令 v-loading

    1 在src下创建directive文件夹 2 在directive文件夹下创建loading文件夹 3 loading文件夹内创建index js和loading vue 目录图 4 index js src directive load
  • QtCreator 快捷键问题记录

    我目前用的QtCreator Mac版8 0 0 具体信息如下 一般来说QtCreator的快捷键和设置项在windows下也是一样的 在QtCreator gt Options gt Environment gt Keyboard中可以找
  • SpringBoot整合office转换与预览

    文章目录 一 介绍 1 简介 2 aspose简介 3 jodconverter简介 二 springboot整合aspose实战 1 前期依赖准备 1 1 介绍 1 2 项目直接引入jar包 1 3 maven添加本地包 2 office