Índice de contenidos
- Introducción
- Conversión usando la imagen de docker libreoffice-unoserver
- Conversión usando LibreOffice
- Conversión usando unoserver
- Conclusiones
1. Introducción
En este tutorial vamos a ver las alternativas que tenemos para convertir programáticamente un documento de office a PDF. En primer lugar usaremos la imagen de docker no oficial que levanta un servicio rest para convertir nuestros documentos usando internamente unoserver, esta imagen es https://hub.docker.com/r/libreofficedocker/libreoffice-unoserver.
Para poder convertir nuestros documentos de office en PDF esta imagen usa unoserver. Unoserver es una librera hecha en python que internamente llama a LibreOffice para convertir los documentos en PDF. Se puede ver el repositorio oficial en https://github.com/unoconv/unoserver.
Para entender el funcionamiento, primero veremos como se usa la imagen de docker y luego como podemos convertir los ficheros directamente usando LibreOffice y/o unoserver directamente. Hay que tener en cuenta que si no queremos depender de una imagen no oficial de docker, siempre podemos hacernos nuestro servicio en cualquier lenguaje y ejecutar los comandos de LibreOffice o Unoserver para poder devolver el PDF. Por ejemplo, la imagen libreoffice-unoserver usa la api hecha en Go https://github.com/libreofficedocker/unoserver-rest-api.
NOTA: Hay que tener en cuenta que por debajo se usa LibreOffice y si el fichero no se puede abrir en LibreOffice o algún formato no es compatible con LibreOffice puede generarse mal o dar algún error.
2. Conversión usando la imagen de docker libreoffice-unoserver
En primer lugar vamos a ver como funciona libreoffice-unoserver. Para levantar la imagen ejectamos:
docker run -p 2004:2004 --name libreoffice-unoserver libreofficedocker/libreoffice-unoserver:3.19
Para comprobar que está funcionando en el puerto 2004, tendremos que ver por consola del contenedor de docker el mensaje Server is running at 0.0.0.0:2004
Vamos a comprobar su uso con un fichero de Excel, uno de Word y otro de PowerPoint usando curl y teniendo en cuenta que tenemos los ficheros
ejemploExcel.xlsx, ejemploWord.docx y ejemploPowerPoint.pptx en nuestra carpeta /Users/cdelhoyo/Downloads
curl --location 'http://127.0.0.1:2004/request' --form 'file=@"/Users/cdelhoyo/Downloads/ejemploExcel.xlsx"' --form 'convert-to="pdf"' --output /Users/cdelhoyo/Downloads/ejemploExcel.pdf
curl --location 'http://127.0.0.1:2004/request' --form 'file=@"/Users/cdelhoyo/Downloads/ejemploWord.docx"' --form 'convert-to="pdf"' --output /Users/cdelhoyo/Downloads/ejemploWord.pdf
curl --location 'http://127.0.0.1:2004/request' --form 'file=@"/Users/cdelhoyo/Downloads/ejemploPowerPoint.pptx"' --form 'convert-to="pdf"' --output /Users/cdelhoyo/Downloads/ejemploPowerPoint.pdf
Después de ejecutar estos tres comandos se nos habrán generado 3 pdfs ejemploExcel.pdf
, ejemploWord.pdf
y ejemploPowerPoint.pdf
en nuestra carpeta /Users/cdelhoyo/Downloads
.
En la siguiente imagen podemos ver un ejemplo de la petición anterior hecha con curl al contenedor de docker usando Postman.
NOTA: En este momento la última versión de libreofficedocker/libreoffice-unoserver es la 3.19, pero es una buena práctica revisar si hay alguna versión más actualizada. Revisar en https://hub.docker.com/r/libreofficedocker/libreoffice-unoserver
3. Conversión usando LibreOffice
Para hacer la conversión vamos a usar la última versión de LibreOffice, en nuestro caso, la 24.2.3 . Lo podemos descargar directamente de su web (https://es.libreoffice.org/descarga/libreoffice/), pero en Mac usaremos brew
para a tener el comando de soffice
en el path.
brew install libreoffice
Una vez instalado LibreOffice en nuestro sistema operativo ya podremos usar su comando para levantar LibreOffice, hacer la conversión y cerrarlo. Siguiendo con el ejemplo anterior en el que usamos ejemploExcel.xlsx
, ejemploWord.docx
y ejemploPowerPoint.pptx
, lanzaremos los comandos:
soffice --headless --convert-to pdf --outdir /Users/cdelhoyo/Downloads /Users/cdelhoyo/Downloads/ejemploExcel.xlsx
soffice --headless --convert-to pdf --outdir /Users/cdelhoyo/Downloads /Users/cdelhoyo/Downloads/ejemploWord.docx
soffice --headless --convert-to pdf --outdir /Users/cdelhoyo/Downloads /Users/cdelhoyo/Downloads/ejemploPowerPoint.pptx
En este caso se nos han vuelto a generar los 3 pdfs ejemploExcel.pdf
, ejemploWord.pdf
y ejemploPowerPoint.pdf
en nuestra carpeta /Users/cdelhoyo/Downloads
. Seguramente nos hayamos dado cuenta de que LibreOffice se ha ejecutado y cerrado 3 veces y para evitar esto, usaremos unoserver.
Una vez que hemos acabado esta parte, podemos desinstalar LibreOffice usando
brew uninstall libreoffice
4. Conversión usando unoserver
Usar directamente el comando de LibreOffice es más fácil, pero, eso cargará LibreOffice en la memoria, convertirá un archivo y luego saldrá de LibreOffice, lo que significa que la próxima vez que convierta un documento, LibreOffice deberá cargarse nuevamente en la memoria. Para evitar eso, LibreOffice tiene un modo de escucha, donde puede escuchar comandos a través de un puerto y cargar y convertir documentos sin salir y volver a cargar el software.
Esto reduce la carga de la CPU al convertir muchos documentos entre un 50% y un 75%, lo que significa que puede convertir entre dos y cuatro veces más documentos al mismo tiempo usando este modo.
Según la documentación oficial, solo aseguran el funcionamiento en Linux. Entonces usaremos una imagen de docker de debian para poder hacer la prueba.
Usaremos la imagen debian:12
con un volumen montado sobre la carpeta /Users/cdelhoyo/Downloads/temp
en la que sacaremos nuestro pdf. Iniciamos el contenedor de docker:
docker run --rm -it --name tutorial-unoserver -v /Users/cdelhoyo/Downloads/temp:/home/temp --entrypoint bash debian:12
Instalamos libreoffice, python y wget para poder bajar archivos
apt update
apt -y install libreoffice python3 python3-pip wget
Comprobamos que tenemos bien instalado python con libreoffice
wget -O find_uno.py https://gist.githubusercontent.com/regebro/036da022dc7d5241a0ee97efdf1458eb/raw/find_uno.py
python3 find_uno.py
La consola debe mostrar algo tipo:
Trying python found at /usr/bin/python3... Success!
Found 1 Pythons with Libreoffice libraries:
/usr/bin/python3
Instalamos unoserver
pip install unoserver --break-system-packages
Lanzamos unoserver con las opciones por defecto (host, puerto, etc..) Se pueden ver estas opciones en https://github.com/unoconv/unoserver.
unoserver
En este momento ya tenemos el servidor escuchando y debemos ver por consola algo tipo:
INFO:unoserver:Starting unoserver 2.1.
INFO:unoserver:Command: libreoffice --headless --invisible --nocrashreport --nodefault --nologo --nofirststartwizard --norestore -env:UserInstallation=file:///tmp/tmp1bw8x3ch --accept=socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;StarOffice.ComponentContext
INFO:unoserver:Server PID: 14423
En otra terminal accedemos al contenedor usando:
docker exec -it tutorial-unoserver bash
Y navegamos al volumen compartido con nuestro PC para hacer la conversión
cd /home/temp
wget https://adictosaltrabajo.com/wp-content/uploads/2024/05/ejemploWord.docx
unoconvert ejemploWord.docx ejemploWord.pdf
En este momento podemos acceder a la carpeta de nuestro PC con el volumen /Users/cdelhoyo/Downloads/temp
y veremos que ya tenemos generado el PDF ejemploWord.pdf
En cualquier momento podemos salir de los contenedores de docker con el comando exit
5. Conclusiones
Si necesitamos convertir documentos de office en pdf dentro de nuestro negocio, deberíamos tener una pieza aislada que se encargue de esto, por lo tanto lo ideal es usar la primera opción con libreoffice-unoserver y si no nos fiamos de una imagen que no esta controlada por nosotros, deberíamos hacer un servicio rest que llame al comando unoconvert y pueda quedar encapsulado en una imagen de docker como hemos hecho en el apartado Conversión usando unoserver. Podríamos usar cualquier lenguaje para hacer una API Rest que invoque el comando unoconvert.
Buen día Carlos.
Le comento que he puesto en práctica las sugerencias para usar Unoserver, y el primero tuve problemas para usar desde una Maquina virtual con Rocky Linux, pero el punto 4 me ha funcionado muy bien. Me ha servido de mucho este artículo. Felicidades por este trabajo.
Buen día Carlos.
Excelente artículo para montar mi propio servicio para convertir documento de DOCX a PDF, el cual me funcionó la opción 4, pero no logre que me funcionara la opción 1. Igual quería tener control de contenedor como lo sugiere.
Ahora necesito saber si se esta usando o no el servicio de unoserver para la conversión, para así controlar cuando si y cuando no enviar una petición de conversión de docx a pdf. Conoce alguna manera de monitorear unoserver desde el contenedor?
Le agradezco mucho su ayuda.