2026/4/7 14:41:41
网站建设
项目流程
番禺网站建设培训,网站建设产品分类,做阿里巴巴网站电话,ui交互设计是什么意思呢一、 背景
因为项目中需要使用word转pdf功能#xff0c;因为转换速度原因#xff0c;最后选用了libreoffice#xff0c;原因及部署请参考 linux ubuntu环境安装libreoffice#xff0c;word转pdf 远程调用的话可选docker部署#xff0c;请看2.3.1
二、springboot整合libr…一、 背景因为项目中需要使用word转pdf功能因为转换速度原因最后选用了libreoffice原因及部署请参考linux ubuntu环境安装libreofficeword转pdf远程调用的话可选docker部署请看2.3.1二、springboot整合libreoffice其实springboot整合libreoffice有两种方式一种是使用本地的libreoffice一种是使用远程服务的libreoffice这个好多文章中没有提到也是自己踩的坑算是2.1、整合本地服务引入pomdependency groupIdorg.jodconverter/groupId artifactIdjodconverter-spring-boot-starter/artifactId version4.4.2/version /dependency dependency groupIdorg.jodconverter/groupId artifactIdjodconverter-local/artifactId version4.4.2/version /dependencyyml配置jodconverter: local: enabled: true #window地址: D:\workplaces\jcxx\libreoffice 请自行补全 #linux地址: /opt/libreoffice24.2 office-home: /opt/libreoffice24.2 # 端口线程 portNumbers: [8101,8102,8103] maxTasksPerProcess: 100 # 任务执行的超时时间 task-execution-timeout: 360000 # 任务队列的超时时间 task-queue-timeout: 360000 # 一个进程的超时时间 process-timeout: 360000使用也很简单Resource private DocumentConverter documentConverter; public void test() { //流转换 documentConverter.convert(inputStream).as(DefaultDocumentFormatRegistry.DOCX).to(outStream).as(DefaultDocumentFormatRegistry.PDF).execute(); //文件转换,sourceFile和targetFile都是File类实例 documentConverter.convert(sourceFile).to(targetFile).as(DefaultDocumentFormatRegistry.PDF).execute(); }2.2、整合远程服务说一下怎么发现的学过springboot的应该都知道整合其他服务时候应该都有个配置类xxxAutoConfiguration于是发现了除了一个local外还有个remote才发现可以直接调用远程服务发现了那就可以整合使用如下pom引入dependency groupIdorg.jodconverter/groupId artifactIdjodconverter-spring-boot-starter/artifactId version4.4.2/version /dependency dependency groupIdorg.jodconverter/groupId artifactIdjodconverter-remote/artifactId version4.4.2/version /dependencyyml配置jodconverter: remote: enabled: true url: http://192.168.1.16:8100 ssl: enabled: false注意一定要加http我就不小心忽略了这个东西只写了个ip端口结果导致一致报错java.net.MalformedURLException: no protocol以下可不看直接看踩坑使用方式和local的一样参考上面不过比local方式多了一步要手动启动远程的libreoffice服务启动命令,附上对应命令的含义https://help.libreoffice.org/latest/zh-CN/text/shared/guide/start_parameters.htmlsoffice --headless --nologo --nofirststartwizard --norestore --acceptsocket,host0.0.0.0,port8100;urp; 以为到此就结束了吗不不不是我想的太简单了对了上面的命令还踩了一些坑百度的时候都是127.0.0.1想telnet通的的话需要使用0.0.0.0不过纠结这个似乎没啥意义原因似乎不在这里当时还花了好久排查不用0.0.0.0的话直接报错连不上对应ip端口改了之后报下面的错2.3、整合远程服务踩坑当我在服务器上运行该命令后满心欢喜的等着转换完成时突然转换就卡住了随后报错org.jodconverter.core.office.OfficeException: Remote conversion failed at org.jodconverter.remote.task.RemoteConversionTask.execute(RemoteConversionTask.java:162) at org.jodconverter.remote.office.RemoteOfficeManagerPoolEntry.doExecute(RemoteOfficeManagerPoolEntry.java:301) at org.jodconverter.core.office.AbstractOfficeManagerPoolEntry.lambda$execute$0(AbstractOfficeManagerPoolEntry.java:80) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: java.net.SocketTimeoutException: Read timed out at java.net.SocketInputStream.socketRead0(SocketInputStream.java) at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) at java.net.SocketInputStream.read(SocketInputStream.java:171) at java.net.SocketInputStream.read(SocketInputStream.java:141) at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:137) at org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:153) at org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:280) at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:138) at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:56) at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259) at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:163) at org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:157) at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273) at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125) at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:272) at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186) at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56) at org.apache.http.client.fluent.Request.internalExecute(Request.java:173) at org.apache.http.client.fluent.Executor.execute(Executor.java:262) at org.jodconverter.remote.task.RemoteConversionTask.execute(RemoteConversionTask.java:147) ... 6 more连接超时我telnet一下端口通啊最最让我恶心的是我上周快下班时候使用这种方式成功转换了一次这就给我一种错觉可能是我启动命令的问题于是就疯狂尝试修改启动命令找对应的参数。结果都没卵用。。。。。。于是想上周是不是搞错了让我误以为这样可行结果还真是命令行启动压根就不能使用remote。不过没找到上周为啥成功的原因也忘了上周咋成功的了。。。https://github.com/jodconverter/jodconverter/wiki/LibreOffice-Remote看到这我就懵了我还得去安装个Collabora Online 或者LibreOffice Online当前这也是可行的。我看了下这两东西基本就是属于web端的在线编辑word了。。。于是又开始找不过这回学聪明了点只在github中的issues中找搜索关键词remote还真让我找出来两种办法但是我只成功了一种对了扔几个issues链接有兴趣的可以看下https://github.com/jodconverter/jodconverter/wiki/Migration-Guide-4.4.5 https://github.com/jodconverter/jodconverter/issues/40 https://github.com/jodconverter/jodconverter/issues/350 https://github.com/jodconverter/jodconverter/issues/3972.3.1、方法一成功也就是https://github.com/jodconverter/jodconverter/issues/397这个里面提到的方案。代码很简单都可以看下简单来说就是本地启动一个libreoffice服务并对外提供接口调用就一个controllerdocker镜像拉不下来参考这个我是看第一点成功的https://blog.csdn.net/weixin_50160384/article/details/139861337jodconverter提供了一个远程服务的接口我们可以直接docker运行docker run -d -p 8100:8100 --privilegedtrue -v /usr/share/fonts:/usr/share/fonts -v /opt/application.properties:/etc/app/application.properties ghcr.io/jodconverter/jodconverter-examples:rest挂载对应字体否则中文不显示-v /usr/share/fonts:/usr/share/fonts挂载配置文件用于修改端口等-v /opt/application.properties:/etc/app/application.properties配置文件在这看https://github.com/jodconverter/docker-image-jodconverter-examples对应文件我也贴下# amount of libreOffice instances to start - one for each given port. So this means 2 jodconverter.local.port-numbers: 2002, 2003 # change the tmp folder jodconverter.local.working-dir: /tmp # change upload sizes spring.servlet.multipart.max-file-size: 5MB spring.servlet.multipart.max-request-size: 5MB # change the server port (where the REST app is listenting server.port8100然后这个的ip端口号使用jodconverter.remote方式就成功了也许有同学已经安装好了libreoffice想着我这libreoffice不白装了最后用docker。。。其实也不然可以自己将项目打个包放到服务器去运行不过这个需要自己研究下了https://github.com/jodconverter/jodconverter-samples不过我看了下dockerfile文件可能是这个命令没用过gradlew 2.3.2、使用local参数但是使用远程服务器失败根据https://github.com/jodconverter/jodconverter/wiki/Migration-Guide-4.4.5描述及https://github.com/jodconverter/jodconverter/issues/40似乎可以使用local来进行访问于是有了如下配置jodconverter: local: enabled: true office-home: D:\workplaces\libreoffice port-numbers: 9999 load-document-mode: remote start-fail-fast: true host-name: 120.46.141.243有一点很让人费解使用了remote模式还必须配置office-home。。。我使用远程服务上的地址还不行。。。还有一点必须要提前启动位于服务器上的9999端口服务不提前启动程序启动不起来。然后我尝试了下虽然也能转换成功但是用了40多秒。不清楚是什么原因解决的小伙伴可以在评论区讨论下soffice --headless --nologo --nofirststartwizard --norestore --acceptsocket,host0.0.0.0,port9999;urp; 三、docker中同时部署应用和libreoffice不推荐单独部署libreoffice的可以自己再查询下这里就不介绍了因为一开始我只发现了local这种方式所以就在window本地和linux服务器上都部署了下后来突然想到丫的服务是用的docker进行部署的。docker里面又没有libreoffice还访问个屁呀我linux部署上没啥用啊意识到这点后首先尝试着把Linux中的libreoffice挂载到docker容器中但以交互模式进去后soffice还是libreoffice24.2都执行不了。。。。那想着只能将libreoffice也弄到容器中去了。。。于是有了下面的dockerfile文件# 使用基于 Alpine 的 OpenJDK 镜像 FROM registry.cn-beijing.aliyuncs.com/hub-mirrors/openjdk:8-jdk-alpine # 更新包列表并安装必要的软件 RUN apk add --no-cache bash libreoffice # 复制 jar 文件到容器 COPY xxx.jar app.jar COPY fonts/zhFonts /usr/share/fonts # 设置环境变量 ENV JAVA_HOME/usr/lib/jvm/default-jvm ENV LIBREOFFICE_HOME/usr/lib/libreoffice ENV PATH$JAVA_HOME/bin:$LIBREOFFICE_HOME/program:$PATH # 设置 ENTRYPOINT 以允许使用 exec ENTRYPOINT [/bin/bash, -c] # 设置 CMD 以启动 Java 应用 CMD [java -Djava.security.egdfile:/dev/./urandom -jar app.jar] #LibreOffice 6.1.4.2 版本也许对docker还是不太熟悉在copy命令的时候源文件似乎不能使用绝对路径这个让我有点奇怪于是把东西全都挪到了/opt目录下然后执行命令注意最后有个.docker build -t新镜像名字:TAG.不推荐的原因就是在于此一个镜像高达1g。。。实测后libreoffice和服务都是正常的可以接受镜像大和构建时间长些的也可以使用这种方式发现这点后我感觉这也太low了毕竟之前jar包也就将近200m而且使用的是阿里的云效流水线构建工具这样构建一次得花多久没有去公司服务器尝试自己用云服务器尝试第一次构建dockerfile拉取libreoffice花了得10多分钟第二次用dockerfile构建就是秒拉取了可能也只是第一次慢不知道用云效如何有兴趣的可以尝试下。尝试着找别的方法解决于是无意中发现了JodConverterRemoteAutoConfiguration对应配置类JodConverterRemoteProperties四、其他问题4.1、使用远程的libreoffice时候用excel转pdf的时候样式错乱本来是这样的格式变成了这样反正发现这个问题我是很懵圈的。但没办法排查呗。尝试下本地的libreoffice另存为是正常的。尝试下代码本地的libreoffice也是正常的。尝试下inux的本地的libreoffice也是正常的。然后我就开始怀疑是不是remote源码层面的问题于是去把remote的代码弄到本地试了下也是正常的。然后我就想着用自己买的服务器试试是不是application配置文件的问题但是我发现我自己服务器的远程服务是正常的。那我就意识到了都是docker容器不一样的只能是挂载文件那问题就只能出在字体上了因为用服务器试过word转pdf没有中文乱码问题之前有人上传了一些字体所以服务器上我就没有上传字体于是就出现了该问题字体还是要上传全的。问题就出在字体上上传上去字体就好了