gpt4 book ai didi

java - 如果超过最大允许时间,如何取消 Libreoffice UNO API 库将 ms Office 文件转换为 PDF 的过程

转载 作者:行者123 更新时间:2023-12-02 05:48:56 24 4
gpt4 key购买 nike

我正在使用 Libreoffice 6.0 中的 UNO API 库 (Soffice) 将 ms office 格式转换为 PDF,Soffice 进程在服务器模式下处理多个并发请求。通常转换速度很快,但在转换一些大文件时,例如xlsx 或 pptx,Soffice 进程使用 100% CPU,转换最多需要几分钟。这是 Not Acceptable ,因为在此期间不会处理并发请求。

为了处理这种情况,我尝试使用 java.util.concurrent 将一些子任务作为线程执行,并通过 future 接口(interface)进行超时控制。但只有当转换的原始 MS Office 文档加载阶段发生挂起时,它才有效。如果转换过程已经开始,即使出现超时异常,Soffice进程也不会立即退出100%负载,而是继续将文档转换为pdf。程序执行暂停,尝试处理加载的文档。

Linux下通过命令启动SOffice进程:

Runtime.getRuntime().exec("/usr/lib64/libreoffice/program/soffice, --nologo, --nodefault, --norestore, --nocrashreport, --nolockcheck, --accept=socket,host=localhost,port=8100;urp;");

将 ms Office 文件转换为简化格式的 pdf 的代码是:

public  void  convertFile(){
xRemoteContext = BootstrapSocketConnector.bootstrap(oooPath);
xRemoteServiceManager = xRemoteContext.getServiceManager();
Object desktop = null;
desktop = xRemoteServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", xRemoteContext);
xComponentLoader = (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class, desktop);
File mfile = new File(workingDir + myTemplate);
String sUrl = pathToURL(workingDir + myTemplate);
PropertyValue[] propertiesIn;
propertiesIn = new PropertyValue[2];
propertiesIn[0] = property("ReadOnly", Boolean.TRUE);
propertiesIn[1] = property("Hidden", Boolean.TRUE);
XComponent xComp = null;
try {
//xComp = xComponentLoader.loadComponentFromURL(sUrl, "_blank", 0, propertiesIn);
//The same via timeout control
xComp = callLibreLoad(sUrl, propertiesIn);
}
catch (TimeoutException ex) {
if(xComp!= null)
xComp.dispose();
...
}
// save as a PDF
XStorable xStorable = (XStorable) UnoRuntime.queryInterface(XStorable.class, xComp);
PropertyValue[] propertiesOut = new PropertyValue[2];
propertiesOut[0] = property("FilterName", formatfilter);
propertiesOut[1] = property("Overwrite", Boolean.TRUE);
String myResult = workingDir + fileNameOut;
try {
//xStorable.storeToURL(pathToURL(myResult), propertiesOut);
//The same via timeout control
callLibreStore(xStorable,pathToURL(myResult), propertiesOut);
}
catch (TimeoutException ex) {
if(xComp!= null)
xComp.dispose();
...
}
if(xComp!= null)
xComp.dispose();
}

函数callLibreLoad和callLibreStore使用Future接口(interface)进行超时控制:

private XComponent callLibreLoad(String sUrl, PropertyValue[] propertiesIn) throws Exception {
XComponent result = null;
ExecutorService executor = Executors.newCachedThreadPool();
Callable<Object> task = new Callable<Object>() {
public Object call() throws IllegalArgumentException, com.sun.star.io.IOException {
return xComponentLoader.loadComponentFromURL(sUrl, "_blank", 0, propertiesIn);
}
};
Future<Object> future = executor.submit(task);
try {
result = (XComponent) future.get(maxTimeout, TimeUnit.SECONDS);
}
finally
{ future.cancel(true);}
return result;
}

private void callLibreStore(XStorable xStorable, String sUrl, PropertyValue[] propertiesOut) throws Exception {
Integer result = null;
ExecutorService executor = Executors.newCachedThreadPool();
Runnable task = new Runnable() {
public void run() {
try {
xStorable.storeToURL(sUrl, propertiesOut);
} catch (com.sun.star.io.IOException e) {
log.error(e);
}
}
};
Future future = executor.submit(task);
try {
future.get(maxTimeout, TimeUnit.SECONDS);
}
finally {
future.cancel(true); // may or may not desire this
}
}

因此,当函数callLibreLoad发生超时异常时,SOffice进程立即恢复到工作状态。但是当稍后发生超时时,在函数 callLibreStore 中,即使发生超时并且转换线程被中断,SOffice 进程仍处于 100% 加载状态超过一分钟,试图处理加载的文档,执行代码 xComp.dispose()。此时,SOffice 进程的 java 线程的堆栈跟踪包含以下内容:

State: WAITING on com.sun.star.lib.uno.environments.remote.JobQueue@30af74b8
Total blocked: 455 Total waited: 1 967
Stack trace:
java.lang.Object.wait(Native Method)
com.sun.star.lib.uno.environments.remote.JobQueue.removeJob(JobQueue.java:207)
com.sun.star.lib.uno.environments.remote.JobQueue.enter(JobQueue.java:316)
com.sun.star.lib.uno.environments.remote.JobQueue.enter(JobQueue.java:289)
com.sun.star.lib.uno.environments.remote.JavaThreadPool.enter(JavaThreadPool.java:81)
com.sun.star.lib.uno.bridges.java_remote.java_remote_bridge.sendRequest(java_remote_bridge.java:618)
com.sun.star.lib.uno.bridges.java_remote.ProxyFactory$Handler.request(ProxyFactory.java:145)
com.sun.star.lib.uno.bridges.java_remote.ProxyFactory$Handler.invoke(ProxyFactory.java:129)
com.sun.proxy.$Proxy211.close(Unknown Source)
com.componentplus.prom.libreoffice.LibreOfficeStationary.closeDocument(LibreOfficeStationary.java:425)
com.componentplus.prom.libreoffice.LibreOfficeStationary.convertFile(LibreOfficeStationary.java:393)
...

如果花费的时间超过最大允许时间,如何强制 Soffice 取消转换为 PDF。

最佳答案

一种可能是保存由 Runtime.getRuntime().exec 返回的 Process 实例,例如保存在变量 myProc 中,然后在需要时调用 myProc.destroy() 来终止进程。

关于java - 如果超过最大允许时间,如何取消 Libreoffice UNO API 库将 ms Office 文件转换为 PDF 的过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56067599/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com