OpenOffice安装及使用

这篇文章详细介绍了Apache OpenOffice的安装、配置,以及如何利用其功能处理Excel、PDF转换,配合Spring Boot中的工具类,展示了PDF转图片和模板Excel到PDF的流程。同时提到了必要的依赖管理和字体设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

OpenOffice概述

​ Apache OpenOffice是一款先进的开源 办公软件套件,它包含文本文档电子表格演示文稿绘图数据库等。 它能够支持许多语言并且在所有普通计算机上工作。它将你所有的数据以国际开放标准格式存储下来,并能够读写从其它常用办公软件包来的文件。

​ 一般使用在文件预览的功能中。

OpenOffice的安装

  • 官网下载安装包

官网地址为:http://www.openoffice.org/

  • 解压下载的安装包
tar -xzvf Apache_OpenOffice_4.1.3_Linux_x86-64_install-rpm_zh-CN.tar.gz 

解压得到的文件夹是 zh-CN

  • 安装编译
cd zh-CN/RPMS/
rpm -ivh *rpm
  • 安装Redhat套件
cd desktop-integration/
rpm -ivh openoffice4.1.3-redhat-menus-4.1.3-9783.noarch.rpm

默认安装在 /opt/openoffice4

  • 更改OpenOffice文件夹用户
chown -R jenkins:jenkins /opt/openoffice4/
  • Supervisor中添加OpenOffice
[program:openoffice]
command=/opt/openoffice4/program/soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard
user=root
autorestart=true
startsecs=5

服务器使用的是Supervisor进行服务器中进程的管理,需要在Supervisor的配置文件中添加如上配置,并执行 supervisorctl update 命令让配置生效

若需要提供给外部使用,需将 host=127.0.0.1 配置改为 host=0.0.0.0

  • 上传中文字体(宋体和黑体)

在Windows电脑的 C:\Windows\Fonts 路径中有相应的字体文件,将其中的宋体和黑体的字体文件进行上传到服务器地址为 /usr/share/fonts,并在文件夹路径中执行相关命令:

mkfontscale
mkfontdir
fc-cache

// 查询服务器中中文字体列表
fc-list :lang=zh 

上传中文字体文件是进行解决项目中使用OpenOffice转换的文件中出现的中文乱码的情况

  • 设置字体文件权限
chmod -R 755 simhei.ttf
chmod -R 755 simsun.ttc

字体文件上传处理完需要重新启动OpenOffice才会生效

OpenOffice的使用

  • 引用依赖
<!--open office依赖-->
<dependency>
    <groupId>com.artofsolving</groupId>
    <artifactId>jodconverter</artifactId>
    <version>${jodconverter.version}</version>
</dependency>

<!--excel处理依赖-->
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-base</artifactId>
    <version>${easypoi-base.version}</version>
</dependency>

<!-- PDF转图片依赖 -->
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>${pdfbox.version}</version>
</dependency>

<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox-tools</artifactId>
    <version>${pdfbox-tools.version}</version>
</dependency>

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>${poi.version}</version>
</dependency>

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>${commons-lang3.version}</version>
</dependency>
  • OpenOffice的相关操作
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import com.artofsolving.jodconverter.DocumentConverter;
import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.converter.OpenOfficeDocumentConverter;
import com.artofsolving.jodconverter.openoffice.converter.StreamOpenOfficeDocumentConverter;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.tools.imageio.ImageIOUtil;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import java.awt.image.BufferedImage;
import java.io.*;
import java.net.ConnectException;
import java.util.HashMap;
import java.util.Map;

import static org.apache.pdfbox.rendering.ImageType.RGB;

/**
 * 项目名称:spring-boot-demo
 * 类名称:OpenOfficeUtil
 * 类描述:OpenOffice工具类
 * 创建人:yingx
 * 创建时间: 2021/2/7
 * 修改人:yingx
 * 修改时间: 2021/2/7
 * 修改备注:
 */
public class OpenOfficeUtil {

    private static final Logger logger = LoggerFactory.getLogger(OpenOfficeUtil.class);

    /**
    * OpenOffice安装的服务器的IP地址
    **/
    public static final String LOCAL_HOST = "";

    public static final int LOCAL_PORT = 8100;

    /**
     * 将项目内的模板输出到系统临时目录
     *
     * @param path : 项目内的模板路径
     * @desc : easypoi的ExcelCache问题(路径转换)
     */
    public static String convertTemplatePath(String path) {
        Resource resource = new ClassPathResource(path);
        FileOutputStream fileOutputStream = null;
        // 将模版文件写入到 tomcat临时目录
        String folder = System.getProperty("java.io.tmpdir");
        File tempFile = new File(folder + File.separator + path);
        // 文件存在时 删除历史临时文件
        if (tempFile.exists()) {
            //删除文件
            tempFile.delete();
        }
        File parentFile = tempFile.getParentFile();
        // 判断父文件夹是否存在
        if (!parentFile.exists()) {
            //不存在则创建
            parentFile.mkdirs();
        }
        try {
            BufferedInputStream bufferedInputStream = new BufferedInputStream(resource.getInputStream());
            fileOutputStream = new FileOutputStream(tempFile);
            byte[] buffer = new byte[10240];
            int len;
            while ((len = bufferedInputStream.read(buffer)) != -1) {
                fileOutputStream.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return tempFile.getPath();
    }

    /**
     * Workbook输出文件
     *
     * @param wb       excel
     * @param fileName 文件
     */
    public static void workbookWriteFile(Workbook wb, String fileName) {
        try (FileOutputStream fileOutputStream = new FileOutputStream(fileName)) {
            wb.write(fileOutputStream);
        } catch (Exception e) {
        }
    }

    /**
     * @param inputFilePath  待转换的文件路径
     * @param outputFilePath 输出文件路径
     * @desc
     * @auth josnow
     * @date 2017年6月9日 下午4:11:04
     */
    public static void convert(String inputFilePath, String outputFilePath) throws ConnectException {
        convert(inputFilePath, outputFilePath, LOCAL_HOST, LOCAL_PORT);
    }

    /**
     * @param inputFilePath  待转换的文件路径
     * @param outputFilePath 输出文件路径
     * @param connectIp      远程调用ip
     * @param connectPort    远程调用端口
     * @desc
     * @auth josnow
     * @date 2017年6月9日 下午4:12:29
     */
    public static void convert(String inputFilePath, String outputFilePath, String connectIp, int connectPort)
        throws ConnectException {
        if (StringUtils.isEmpty(inputFilePath) || StringUtils.isEmpty(outputFilePath) || StringUtils.isEmpty(
            connectIp)) {

            logger.error("inputFilePath={}, outputFilePath={}, connectIp={}", inputFilePath, outputFilePath, connectIp);

            throw new IllegalArgumentException("参数异常!!");
        }
        File inputFile = new File(inputFilePath);
        File outputFile = new File(outputFilePath);

        if (!inputFile.exists()) {
            logger.error(inputFilePath + "输入文件不存在!");
            throw new IllegalArgumentException("输入文件不存在!");
        }

        if (!outputFile.getPath()
            .equals(outputFile.getAbsolutePath())) {
            logger.warn("输出文件采用相对路径!相对路径为:{} ,绝对路径为:{}", outputFile.getPath(),
                outputFile.getAbsolutePath());
        }

        File outputFilePa = outputFile.getParentFile();
        if (outputFilePa != null && !outputFilePa.exists()) {
            // 目录不存在则创建
            boolean mkdirs = outputFilePa.mkdirs();
            if (!mkdirs) {
                logger.error("输出文件目录创建失败:" + outputFilePa.getAbsolutePath());
            }
        }

        OpenOfficeConnection connection = new SocketOpenOfficeConnection(connectIp, connectPort);
        connection.connect();

        DocumentConverter converter = getConverter(connectIp, connection);

        converter.convert(new File(inputFilePath), new File(outputFilePath));
        connection.disconnect();
    }

    private static DocumentConverter getConverter(String connectIp, OpenOfficeConnection connection) {
        return "localhost".equalsIgnoreCase(connectIp) || "127.0.0.1".equals(connectIp)
            || "0:0:0:0:0:0:0:1".equals(connectIp) ? new OpenOfficeDocumentConverter(connection) :
            new StreamOpenOfficeDocumentConverter(connection);
    }

    /**
     * 实现PDF转图片
     *
     * @param pdfFile
     * @author yingx
     * @date 2020/12/29
     */
    public static void pdf2Image(File pdfFile) throws IOException {

        // 生成图片后的路径
        String path = pdfFile.getParent() + File.separator;
        String fileName = pdfFile.getName().replace(".pdf", "");

        PDDocument doc = PDDocument.load(pdfFile);
        BufferedImage imageNew = null;
        PDFRenderer pdfRenderer = new PDFRenderer(doc);
        int pageCounter = 0;
        int width = 0;
        int height = 0;
        for (PDPage page : doc.getPages()) {
            //dpi为缩放参数,越小图片越模糊
            BufferedImage bim = pdfRenderer.renderImageWithDPI(pageCounter++, 100, RGB);
            // 图片宽度 图片高度
            width = Math.max(width, bim.getWidth());
            height = Math.max(height, bim.getHeight());
        }
        int count = doc.getPages().getCount();
        //多张图片垂直排列  , 所以长度要叠加
        imageNew = new BufferedImage(width, height * count, BufferedImage.TYPE_INT_RGB);
        pageCounter = 0;
        for (PDPage page : doc.getPages()) {
            BufferedImage bim = pdfRenderer.renderImageWithDPI(pageCounter++, 100, RGB);
            // 图片宽度 图片高度
            int w = bim.getWidth();
            int h = bim.getHeight();
            int[] imageArrayOne = new int[width * height];
            imageArrayOne = bim.getRGB(0, 0, w, h, imageArrayOne, 0, w);
            // 第三,第四参数,不是终点位置,而是要填充内容的 宽  高
            imageNew.setRGB(0, height * (pageCounter - 1), w, h, imageArrayOne, 0, w);
        }
        ImageIOUtil.writeImage(imageNew, path + fileName + ".png", 100);
        doc.close();
    }
    
    /**
     * 保存pdf到本地磁盘
     *
     * @param pdfSavePath pdf保存路径
     * @param pdfContent  pdf内容
     */
    public static void savePdfToDisk(String pdfSavePath, String pdfContent) {
        byte[] decodeBase64 = org.apache.commons.codec.binary.Base64.decodeBase64(pdfContent);
        //修复异常数据
        for (int i = 0; i < decodeBase64.length; i++) {
            if (decodeBase64[i] < 0) {
                decodeBase64[i] += 256;
            }
        }
        try (OutputStream out = new FileOutputStream(pdfSavePath)) {
            logger.info("将Base64的PDF文件进行保存至 ---{}", pdfSavePath);
            IOUtils.write(decodeBase64, out);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  • OpenOffice的使用
public static void main(String[] args) throws IOException {
    // 获取项目内 Excel模板路径
    String excelTemplate = "templates/test_template.xls";
    // 获取生成pdf的存储路径
    String pdfPath = OpenOfficeUtil.convertTemplatePath(excelTemplate);

    // 初始化 Excel 模板参数
    TemplateExportParams params = new TemplateExportParams(pdfPath);

    Map<String, Object> templateData = new HashMap<>(16);
    templateData.put("Name", "java");

    Workbook workbook = ExcelExportUtil.exportExcel(params, templateData);

    String pdfName = "测试.pdf";

    String exportFilePath = String.join("/", "/srv/upload/attachments", "test") + "/";
    String xlseName = "test_template.xls";

    File pdfAddressFolder = new File(exportFilePath);
    if (StringUtils.isEmpty(exportFilePath)) {
        logger.info("pdf文件夹配置为空");
    } else if (!pdfAddressFolder.exists()) {
        // 目录不存在则创建
        boolean mkdirs = pdfAddressFolder.mkdirs();
        if (!mkdirs) {
            logger.error("输出文件目录创建失败 ---{}", pdfAddressFolder.getAbsolutePath());
        }
    }
    String fullPdfName = exportFilePath + pdfName;
    String xlsePath = exportFilePath + xlseName;
    if (workbook != null) {
        OpenOfficeUtil.workbookWriteFile(workbook, xlsePath);
        OpenOfficeUtil.convert(xlsePath, fullPdfName);
        //PDF转成图片并存储服务器中(PDF文件同一路径)
        OpenOfficeUtil.pdf2Image(new File(fullPdfName));
    }
}

剩下的就是将Excel模板文件放置在项目的 src\main\resources\templates目录下,并在模板中需要添加数据的位置添加占位符,如上代码需要使用 {{Name}} 占位符,执行完代码后,该位置将会替换成 对应的数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值