Crate office_to_pdf

Source
Expand description

§Office To PDF

Converts office files to PDF files

This library is a Rust wrapper around unoserver which uses LibreOffice to convert the office files to PDF.

Supports handling remote unoserver instances and load balancing traffic between multiple unoserver instances

[!IMPORTANT] Only supported on Linux targets

§Installation

Install LibreOffice, Python 3, and Python 3 pip (Command for Debian, apt package manager. Adjust for your distro):

sudo apt-get install -y libreoffice python3 python3-pip

Install unoserver pip module

sudo pip install unoserver

unoserver must be on your path if you want to start a server unoconvert must be on your path if you want to convert files

Both should be on your path by default after installing unoserver.

§Start server instance

You can start unoserver using the following code:

use office_to_pdf::{start_unoserver, ConvertServer, ConvertLoadBalancer, ConvertServerHost};
use std::time::Duration;

// Create the server
let server = ConvertServer::new(ConvertServerHost::Local { port: 2003 });

// Check the server isn't already running
if server.is_running(ConvertServer::DEFAULT_RUNNING_TIMEOUT).await {
    
    // Start the server (The second port must be unique and not in use, its used by libreoffice)
    start_unoserver(2003, 2002).await.unwrap();
}

This server will be stopped when our program stops (Or earlier if you call .abort() on its handle) because of this its recommended if your using this as a long running server to instead run unoserver as a background OS service.

§Default server

The default example will use the default server port (2003)

use office_to_pdf::ConvertServer;

let input_bytes = &[/* YOUR INPUT BYTES */]
let output = ConvertServer::default()
    .convert_to_pdf(input_bytes)
    .await
    .unwrap();

[!INFO] You must have the unoserver running at the same time for this to work.

Or you can start one using the command above

§Custom local server port

You can specify a custom port for a local server using the following:

use office_to_pdf::{ConvertServer, ConvertServerHost};

let input_bytes = &[/* YOUR INPUT BYTES */]
let output = ConvertServer::new(ConvertServerHost::Local { port: 5000 })
    .convert_to_pdf(input_bytes)
    .await
    .unwrap();

§Remote unoserver

You can specify a remote server using the following:

use office_to_pdf::{ConvertServer, ConvertServerHost};

let input_bytes = &[/* YOUR INPUT BYTES */]
let output = ConvertServer::new(ConvertServerHost::Remote {
    host: "10.0.2.1".to_string(),
    port: 5000,
})
.convert_to_pdf(input_bytes)
.await
.unwrap();

§Load balancing

Converting larger files can block a unoserver for some period of time. You can run multiple unoserver instances and use a load balancer to distribute load amongst the various servers.

The servers will be checked to see if they are busy and the next free server will be used instead:

use office_to_pdf::{ConvertServer, ConvertLoadBalancer, ConvertServerHost};
use std::time::Duration;
use tokio::task::JoinSet;

let pool = ConvertLoadBalancer::new(
    // Available servers
    vec![
        ConvertServer::new(ConvertServerHost::Remote {
            host: "localhost".to_string(),
            port: 9250,
        }),
        ConvertServer::new(ConvertServerHost::Remote {
            host: "localhost".to_string(),
            port: 9251,
        }),
        ConvertServer::new(ConvertServerHost::Remote {
            host: "localhost".to_string(),
            port: 9252,
        }),
        ConvertServer::new(ConvertServerHost::Remote {
            host: "localhost".to_string(),
            port: 9253,
        }),
        ConvertServer::new(ConvertServerHost::Remote {
            host: "localhost".to_string(),
            port: 9254,
        }),
    ],
    // Maximum connect timeout
    Duration::from_millis(200),
    // Busy check timeout (Time allowed for a response before server is considered busy)
    Duration::from_millis(500),
);

let mut join_set = JoinSet::new();

// Sample test to spawn 50 conversions distributed amongst the servers
for _ in 0..50 {
    let pool = pool.clone();

    join_set.spawn(async move {
        let input_bytes = &[ /* YOUR INPUT BYTES */ ];
        pool.handle(input_bytes).await.unwrap();
    });
}

while (join_set.join_next().await).is_some() {}

§Checking convertable

You can check if a mime type is supported for conversion using the following:

use office_to_pdf::is_known_convertable;

let mime = "text/plain";
let is_convertable = is_known_convertable(mime);

Structs§

ConvertLoadBalancer
Simple load balancer for distributing load amongst the provided servers.
ConvertServer
Convert server
LocalServer
Unoserver instance managed locally within the process.
LocalServerPool
Pool of locally allocated servers

Enums§

ConvertError
Errors that can occur while converting an office file
ConvertServerHost
Server connection details
ConvertServerState
State for a converter server
ServerError
Error when starting an unoserver

Constants§

CONVERTABLE_FORMATS
List of supported convertable formats
DEFAULT_SERVER_PORT
Default port for unoserver
DEFAULT_UNO_PORT
Default port for the Libreoffice uno

Functions§

is_known_convertable
Checks if the provided mime is included in the known convertable mime types
start_unoserver
Start a unoserver instance