天天看點

jodconverter實作線上預覽

jodconverter實作線上預覽

現在預覽是一個非常常用的供能。項目經理在會上提出必須實作改功能。首先部落客先确定了一個思路:其他文檔轉成配pdf然後通過流發送到前台。因為前台支援pdf,可以直接預覽。說幹就幹。下面上代碼。

1.方案一:使用jodconverter-spring-boot-starter方法

在一些時間的調研後,發現spring提供jodconverter-spring-boot-starter的jar包。能夠完成該功能。我們隻需要按照他的API實作即可。

1.修改pom檔案

<!--jodconverter 核心包 -->
        <dependency>
            <groupId>org.jodconverter</groupId>
            <artifactId>jodconverter-core</artifactId>
            <version>4.2.2</version>
        </dependency>

        <!--springboot支援包,裡面包括了自動配置類 -->
        <dependency>
            <groupId>org.jodconverter</groupId>
            <artifactId>jodconverter-spring-boot-starter</artifactId>
            <version>4.2.2</version>
        </dependency>


        <!--jodconverter 本地支援包 -->
        <dependency>
            <groupId>org.jodconverter</groupId>
            <artifactId>jodconverter-local</artifactId>
            <version>4.2.2</version>
        </dependency>
      

2.修改application.xml

jodconverter:
  local:
    enabled: true
    max-tasks-per-process: 10
    port-numbers: 8100      

3.調用方法

@RestController
public class OnlinePreviewController {

    // 第一步:轉換器直接注入
    @Autowired
    DocumentConverter documentConverter;

    @GetMapping("/toPdfFile")
    public String toPdfFile(FileMessage fileMessage) {
        // 擷取HttpServletResponse
        HttpServletResponse response =
            ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
        // 需要轉換的檔案
        File file = new File(fileMessage.getFileDownloadUri());
        try {
            // 轉換之後檔案生成的位址
            File newFile = new File("D:/common_files/pdf");
            if (!newFile.exists()) {
                newFile.mkdirs();
            }
            String converterPdf = "D:/common_files/pdf" + "/" + fileMessage.getFileName() + "-pdf.pdf";
            // 檔案轉化
            documentConverter.convert(file).to(new File(converterPdf)).execute();
            // 使用response,将pdf檔案以流的方式發送的前段
            ServletOutputStream outputStream = response.getOutputStream();
            // 讀取檔案
            InputStream in = new FileInputStream(new File(converterPdf));
            // copy檔案
            int i = IOUtils.copy(in, outputStream);
            System.out.println(i);
            in.close();
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "This is to pdf";
    }
}      

但是這種會發生excle過長穿行的情況,放棄。。。

2.方案二:使用com.artofsolving包

在經過又一番調研後,發現com.artofsolving也能實作該功能。

<dependency>
            <groupId>com.artofsolving</groupId>
            <artifactId>jodconverter</artifactId>
            <version>2.2.2</version>
        </dependency>

        <dependency>
            <groupId>org.openoffice</groupId>
            <artifactId>jurt</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.openoffice</groupId>
            <artifactId>ridl</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.openoffice</groupId>
            <artifactId>juh</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.openoffice</groupId>
            <artifactId>unoil</artifactId>
            <version>3.0.1</version>
        </dependency>      

注意2.2.2是在maven伺服器上沒有m是以需要單獨下載下傳處理,直接上網盤位址。

連結:

https://pan.baidu.com/s/1d5oe7OIaq6Wi-wR70860jA

提取碼:touy

2.Controller類

import com.artofsolving.jodconverter.DocumentConverter;
import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
import org.apache.commons.io.IOUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

@RestController
public class OnlinePreviewController {

    @GetMapping("/toPdfFile")
    public void toPdfFile(FileMessage fileMessage) throws IOException {
        // 擷取HttpServletResponse
        HttpServletResponse response =
            ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
        // 源檔案目錄
        File inputFile = new File(fileMessage.getFileDownloadUri());
        if (!inputFile.exists()) {
            System.out.println("源檔案不存在!");
            return;
        }
        // 轉換之後檔案生成的位址
        File newFile = new File("D:/common_files/pdf");
        if (!newFile.exists()) {
            newFile.mkdirs();
        }
        String converterPdf = "D:/common_files/pdf" + "/" + fileMessage.getFileName() + "-pdf.pdf";
        // 輸出檔案目錄
        File outputFile = new File(converterPdf);
        if (!outputFile.getParentFile().exists()) {
            outputFile.getParentFile().exists();
        }
        // 調用openoffice服務線程
        String command =
            "C:/Program Files (x86)/OpenOffice 4/program/soffice.exe -headless -accept=\"socket,host=127.0.0.1,port=8100;urp;\"";
        Process p = Runtime.getRuntime().exec(command);
        // 連接配接openoffice服務
        OpenOfficeConnection connection = new SocketOpenOfficeConnection("127.0.0.1", 8100);
        connection.connect();
        // 轉換
        DocumentConverter converter = new ConverterDocument(connection);
        converter.convert(inputFile, outputFile);
        ServletOutputStream outputStream = response.getOutputStream();
        // 讀取檔案
        InputStream in = new FileInputStream(new File(converterPdf));
        // copy檔案
        int i = IOUtils.copy(in, outputStream);
        in.close();
        outputStream.close();
        // 關閉連接配接
        connection.disconnect();
        // 關閉程序
        p.destroy();
        System.out.println("轉換完成!");
    }
}      

其中轉換方法為:

DocumentConverter converter = new ConverterDocument(connection);
        converter.convert(inputFile, outputFile);      

因為excel折行問題 是以我們把紙張改變 重寫了ConverterDocument。

3.ConverterDocument

import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.converter.StreamOpenOfficeDocumentConverter;
import com.sun.star.awt.Size;
import com.sun.star.beans.PropertyValue;
import com.sun.star.lang.XComponent;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.view.PaperFormat;
import com.sun.star.view.XPrintable;

public class ConverterDocument extends StreamOpenOfficeDocumentConverter {

    public ConverterDocument(OpenOfficeConnection connection) {
        super(connection);
    }

    public final static Size A5, A4, A3;
    public final static Size B4, B5, B6;
    public final static Size paperSize;
    static {
        A5 = new Size(14800, 21000);
        A4 = new Size(21000, 29700);
        A3 = new Size(29700, 42000);
        B4 = new Size(25000, 35300);
        B5 = new Size(17600, 25000);
        B6 = new Size(12500, 17600);
        // 最大限度 寬 1600000
        paperSize = new Size(29700, 27940);
    }

    @Override
    protected void refreshDocument(XComponent document) {
        super.refreshDocument(document);
        XPrintable xPrintable = (XPrintable)UnoRuntime.queryInterface(XPrintable.class, document);
        PropertyValue[] printerDesc = new PropertyValue[2];
        // 轉換
        printerDesc[0] = new PropertyValue();
        printerDesc[0].Name = "PaperFormat";
        printerDesc[0].Value = PaperFormat.USER;
        // 紙張大小
        printerDesc[1] = new PropertyValue();
        printerDesc[1].Name = "PaperSize";
        printerDesc[1].Value = paperSize;
        try {
            xPrintable.setPrinter(printerDesc);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}      

但是這裡有一個問題,多sheet頁,隻有第一頁改變了,是以解決辦法想了兩個。

  1. 将多個sheet合成一個。
  2. 将多sheet也分開列印。

但是因為偶然機會發現了kkFileView 開源項目,emmmmmmmm,真香。