移除office-plugin, 使用新版jodconverter

This commit is contained in:
陈精华
2022-12-15 18:19:30 +08:00
parent 281a9cfbab
commit 7d3a4ebc4e
12562 changed files with 202 additions and 3641 deletions

View File

@@ -1,6 +1,6 @@
package cn.keking.config;
import org.artofsolving.jodconverter.util.ConfigUtils;
import cn.keking.utils.ConfigUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

View File

@@ -1,7 +1,6 @@
package cn.keking.config;
import org.artofsolving.jodconverter.office.OfficeUtils;
import org.artofsolving.jodconverter.util.ConfigUtils;
import cn.keking.utils.ConfigUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@@ -59,7 +58,7 @@ public class ConfigRefreshComponent {
FileReader fileReader = new FileReader(configFilePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);
properties.load(bufferedReader);
OfficeUtils.restorePropertiesFromEnvFormat(properties);
ConfigUtils.restorePropertiesFromEnvFormat(properties);
cacheEnabled = Boolean.parseBoolean(properties.getProperty("cache.enabled", ConfigConstants.DEFAULT_CACHE_ENABLED));
text = properties.getProperty("simText", ConfigConstants.DEFAULT_TXT_TYPE);
media = properties.getProperty("media", ConfigConstants.DEFAULT_MEDIA_TYPE);

View File

@@ -1,7 +1,6 @@
package cn.keking.model;
import cn.keking.config.ConfigConstants;
import org.artofsolving.jodconverter.model.FileProperties;
/**
* Created by kl on 2018/1/17.
@@ -38,12 +37,6 @@ public class FileAttribute {
this.officePreviewType = officePreviewType;
}
public FileProperties toFileProperties() {
FileProperties fileProperties = new FileProperties();
fileProperties.setFilePassword(filePassword);
return fileProperties;
}
public String getFileKey() {
return fileKey;
}

View File

@@ -1,157 +0,0 @@
package cn.keking.service;
import org.artofsolving.jodconverter.document.DocumentFamily;
import org.artofsolving.jodconverter.document.DocumentFormat;
import org.artofsolving.jodconverter.document.SimpleDocumentFormatRegistry;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 重写了DefaultDocumentFormatRegistry类因为要添加自定义行为比如字符编码。。。
* @author yudian-it
* @date 2017/12/5
*/
public class OfficePluginExtendFormatRegistry extends SimpleDocumentFormatRegistry {
public OfficePluginExtendFormatRegistry() {
DocumentFormat pdf = new DocumentFormat("Portable Document Format", "pdf", "application/pdf");
pdf.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "writer_pdf_Export"));
pdf.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "calc_pdf_Export"));
pdf.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "impress_pdf_Export"));
pdf.setStoreProperties(DocumentFamily.DRAWING, Collections.singletonMap("FilterName", "draw_pdf_Export"));
addFormat(pdf);
DocumentFormat swf = new DocumentFormat("Macromedia Flash", "swf", "application/x-shockwave-flash");
swf.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "impress_flash_Export"));
swf.setStoreProperties(DocumentFamily.DRAWING, Collections.singletonMap("FilterName", "draw_flash_Export"));
addFormat(swf);
// disabled because it's not always available
//DocumentFormat xhtml = new DocumentFormat("XHTML", "xhtml", "application/xhtml+xml");
//xhtml.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "XHTML Writer File"));
//xhtml.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "XHTML Calc File"));
//xhtml.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "XHTML Impress File"));
//addFormat(xhtml);
DocumentFormat html = new DocumentFormat("HTML", "html", "text/html");
// HTML is treated as Text when supplied as input, but as an output it is also
// available for exporting Spreadsheet and Presentation formats
html.setInputFamily(DocumentFamily.TEXT);
html.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "HTML (StarWriter)"));
Map<String,Object> htmlLoadAndStoreProperties = new LinkedHashMap<>();
htmlLoadAndStoreProperties.put("FilterName", "HTML (StarCalc)");
htmlLoadAndStoreProperties.put("FilterOptions", "utf8");
html.setStoreProperties(DocumentFamily.SPREADSHEET, htmlLoadAndStoreProperties);
html.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "impress_html_Export"));
addFormat(html);
DocumentFormat odt = new DocumentFormat("OpenDocument Text", "odt", "application/vnd.oasis.opendocument.text");
odt.setInputFamily(DocumentFamily.TEXT);
odt.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "writer8"));
addFormat(odt);
DocumentFormat sxw = new DocumentFormat("OpenOffice.org 1.0 Text Document", "sxw", "application/vnd.sun.xml.writer");
sxw.setInputFamily(DocumentFamily.TEXT);
sxw.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "StarOffice XML (Writer)"));
addFormat(sxw);
DocumentFormat doc = new DocumentFormat("Microsoft Word", "doc", "application/msword");
doc.setInputFamily(DocumentFamily.TEXT);
doc.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "MS Word 97"));
addFormat(doc);
DocumentFormat docx = new DocumentFormat("Microsoft Word 2007 XML", "docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
docx.setInputFamily(DocumentFamily.TEXT);
addFormat(docx);
DocumentFormat rtf = new DocumentFormat("Rich Text Format", "rtf", "text/rtf");
rtf.setInputFamily(DocumentFamily.TEXT);
rtf.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "Rich Text Format"));
addFormat(rtf);
DocumentFormat wpd = new DocumentFormat("WordPerfect", "wpd", "application/wordperfect");
wpd.setInputFamily(DocumentFamily.TEXT);
addFormat(wpd);
DocumentFormat txt = new DocumentFormat("Plain Text", "txt", "text/plain");
txt.setInputFamily(DocumentFamily.TEXT);
Map<String,Object> txtLoadAndStoreProperties = new LinkedHashMap<>();
txtLoadAndStoreProperties.put("FilterName", "Text (encoded)");
txtLoadAndStoreProperties.put("FilterOptions", "utf8");
txt.setLoadProperties(txtLoadAndStoreProperties);
txt.setStoreProperties(DocumentFamily.TEXT, txtLoadAndStoreProperties);
addFormat(txt);
DocumentFormat wikitext = new DocumentFormat("MediaWiki wikitext", "wiki", "text/x-wiki");
wikitext.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "MediaWiki"));
//addFormat(wikitext);
DocumentFormat ods = new DocumentFormat("OpenDocument Spreadsheet", "ods", "application/vnd.oasis.opendocument.spreadsheet");
ods.setInputFamily(DocumentFamily.SPREADSHEET);
ods.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "calc8"));
addFormat(ods);
DocumentFormat sxc = new DocumentFormat("OpenOffice.org 1.0 Spreadsheet", "sxc", "application/vnd.sun.xml.calc");
sxc.setInputFamily(DocumentFamily.SPREADSHEET);
sxc.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "StarOffice XML (Calc)"));
addFormat(sxc);
DocumentFormat xls = new DocumentFormat("Microsoft Excel", "xls", "application/vnd.ms-excel");
xls.setInputFamily(DocumentFamily.SPREADSHEET);
xls.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "MS Excel 97"));
addFormat(xls);
DocumentFormat xlsx = new DocumentFormat("Microsoft Excel 2007 XML", "xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
xlsx.setInputFamily(DocumentFamily.SPREADSHEET);
addFormat(xlsx);
DocumentFormat csv = new DocumentFormat("Comma Separated Values", "csv", "text/csv");
csv.setInputFamily(DocumentFamily.SPREADSHEET);
Map<String,Object> csvLoadAndStoreProperties = new LinkedHashMap<>();
csvLoadAndStoreProperties.put("FilterName", "Text - txt - csv (StarCalc)");
csvLoadAndStoreProperties.put("FilterOptions", "44,34,0"); // Field Separator: ','; Text Delimiter: '"'
csv.setLoadProperties(csvLoadAndStoreProperties);
csv.setStoreProperties(DocumentFamily.SPREADSHEET, csvLoadAndStoreProperties);
addFormat(csv);
DocumentFormat tsv = new DocumentFormat("Tab Separated Values", "tsv", "text/tab-separated-values");
tsv.setInputFamily(DocumentFamily.SPREADSHEET);
Map<String,Object> tsvLoadAndStoreProperties = new LinkedHashMap<>();
tsvLoadAndStoreProperties.put("FilterName", "Text - txt - csv (StarCalc)");
tsvLoadAndStoreProperties.put("FilterOptions", "9,34,0"); // Field Separator: '\t'; Text Delimiter: '"'
tsv.setLoadProperties(tsvLoadAndStoreProperties);
tsv.setStoreProperties(DocumentFamily.SPREADSHEET, tsvLoadAndStoreProperties);
addFormat(tsv);
DocumentFormat odp = new DocumentFormat("OpenDocument Presentation", "odp", "application/vnd.oasis.opendocument.presentation");
odp.setInputFamily(DocumentFamily.PRESENTATION);
odp.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "impress8"));
addFormat(odp);
DocumentFormat sxi = new DocumentFormat("OpenOffice.org 1.0 Presentation", "sxi", "application/vnd.sun.xml.impress");
sxi.setInputFamily(DocumentFamily.PRESENTATION);
sxi.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "StarOffice XML (Impress)"));
addFormat(sxi);
DocumentFormat ppt = new DocumentFormat("Microsoft PowerPoint", "ppt", "application/vnd.ms-powerpoint");
ppt.setInputFamily(DocumentFamily.PRESENTATION);
ppt.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "MS PowerPoint 97"));
addFormat(ppt);
DocumentFormat pptx = new DocumentFormat("Microsoft PowerPoint 2007 XML", "pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation");
pptx.setInputFamily(DocumentFamily.PRESENTATION);
addFormat(pptx);
DocumentFormat odg = new DocumentFormat("OpenDocument Drawing", "odg", "application/vnd.oasis.opendocument.graphics");
odg.setInputFamily(DocumentFamily.DRAWING);
odg.setStoreProperties(DocumentFamily.DRAWING, Collections.singletonMap("FilterName", "draw8"));
addFormat(odg);
DocumentFormat svg = new DocumentFormat("Scalable Vector Graphics", "svg", "image/svg+xml");
svg.setStoreProperties(DocumentFamily.DRAWING, Collections.singletonMap("FilterName", "draw_svg_Export"));
addFormat(svg);
}
}

View File

@@ -1,12 +1,12 @@
package cn.keking.service;
import com.sun.star.document.UpdateDocMode;
import cn.keking.utils.LocalOfficeUtils;
import org.apache.commons.lang3.StringUtils;
import org.artofsolving.jodconverter.OfficeDocumentConverter;
import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration;
import org.artofsolving.jodconverter.office.OfficeManager;
import org.artofsolving.jodconverter.office.OfficeUtils;
import org.artofsolving.jodconverter.util.PlatformUtils;
import org.jodconverter.core.office.InstalledOfficeManagerHolder;
import org.jodconverter.core.office.OfficeException;
import org.jodconverter.core.office.OfficeUtils;
import org.jodconverter.core.util.OSUtils;
import org.jodconverter.local.office.LocalOfficeManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
@@ -21,16 +21,13 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* 创建文件转换器
*
* @author yudian-it
* @date 2017/11/13
* @author chenjh
* @since 2022-12-15
*/
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
@@ -38,7 +35,7 @@ public class OfficePluginManager {
private final Logger logger = LoggerFactory.getLogger(OfficePluginManager.class);
private OfficeManager officeManager;
private LocalOfficeManager officeManager;
@Value("${office.plugin.server.ports:2001,2002}")
private String serverPorts;
@@ -50,8 +47,8 @@ public class OfficePluginManager {
* 启动Office组件进程
*/
@PostConstruct
public void startOfficeManager() {
File officeHome = OfficeUtils.getDefaultOfficeHome();
public void startOfficeManager() throws OfficeException {
File officeHome = LocalOfficeUtils.getDefaultOfficeHome();
if (officeHome == null) {
throw new RuntimeException("找不到office组件请确认'office.home'配置是否有误");
}
@@ -60,45 +57,26 @@ public class OfficePluginManager {
logger.warn("检测到有正在运行的office进程已自动结束该进程");
}
try {
DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration();
configuration.setOfficeHome(officeHome);
String[] portsString = serverPorts.split(",");
int[] ports = Arrays.stream(portsString).mapToInt(Integer::parseInt).toArray();
configuration.setPortNumbers(ports);
long timeout = DurationStyle.detectAndParse(timeOut).toMillis();
// 设置任务执行超时为5分钟
configuration.setTaskExecutionTimeout(timeout);
// 设置任务队列超时为24小时
//configuration.setTaskQueueTimeout(1000 * 60 * 60 * 24L);
officeManager = configuration.buildOfficeManager();
officeManager = LocalOfficeManager.builder()
.officeHome(officeHome)
.portNumbers(ports)
.processTimeout(timeout)
.build();
officeManager.start();
InstalledOfficeManagerHolder.setInstance(officeManager);
} catch (Exception e) {
logger.error("启动office组件失败请检查office组件是否可用");
throw e;
}
}
public OfficeDocumentConverter getDocumentConverter() {
OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager, new OfficePluginExtendFormatRegistry());
converter.setDefaultLoadProperties(getLoadProperties());
return converter;
}
private Map<String, ?> getLoadProperties() {
Map<String, Object> loadProperties = new HashMap<>(10);
loadProperties.put("Hidden", true);
loadProperties.put("ReadOnly", true);
loadProperties.put("UpdateDocMode", UpdateDocMode.QUIET_UPDATE);
loadProperties.put("CharacterSet", StandardCharsets.UTF_8.name());
return loadProperties;
}
private boolean killProcess() {
boolean flag = false;
try {
if (PlatformUtils.isWindows()) {
if (OSUtils.IS_OS_WINDOWS) {
Process p = Runtime.getRuntime().exec("cmd /c tasklist ");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream os = p.getInputStream();
@@ -111,21 +89,7 @@ public class OfficePluginManager {
Runtime.getRuntime().exec("taskkill /im " + "soffice.bin" + " /f");
flag = true;
}
} else if (PlatformUtils.isLinux()) {
Process p = Runtime.getRuntime().exec(new String[]{"sh", "-c", "ps -ef | grep " + "soffice.bin" + " |grep -v grep | wc -l"});
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream os = p.getInputStream();
byte[] b = new byte[256];
while (os.read(b) > 0) {
baos.write(b);
}
String s = baos.toString();
if (!s.startsWith("0")) {
String[] cmd = {"sh", "-c", "ps -ef | grep soffice.bin | grep -v grep | awk '{print \"kill -9 \"$2}' | sh"};
Runtime.getRuntime().exec(cmd);
flag = true;
}
} else {
} else if (OSUtils.IS_OS_MAC || OSUtils.IS_OS_MAC_OSX) {
Process p = Runtime.getRuntime().exec(new String[]{"sh", "-c", "ps -ef | grep " + "soffice.bin"});
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream os = p.getInputStream();
@@ -139,6 +103,20 @@ public class OfficePluginManager {
Runtime.getRuntime().exec(cmd);
flag = true;
}
} else {
Process p = Runtime.getRuntime().exec(new String[]{"sh", "-c", "ps -ef | grep " + "soffice.bin" + " |grep -v grep | wc -l"});
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream os = p.getInputStream();
byte[] b = new byte[256];
while (os.read(b) > 0) {
baos.write(b);
}
String s = baos.toString();
if (!s.startsWith("0")) {
String[] cmd = {"sh", "-c", "ps -ef | grep soffice.bin | grep -v grep | awk '{print \"kill -9 \"$2}' | sh"};
Runtime.getRuntime().exec(cmd);
flag = true;
}
}
} catch (IOException e) {
logger.error("检测office进程异常", e);
@@ -150,7 +128,7 @@ public class OfficePluginManager {
public void destroyOfficeManager() {
if (null != officeManager && officeManager.isRunning()) {
logger.info("Shutting down office process");
officeManager.stop();
OfficeUtils.stopQuietly(officeManager);
}
}

View File

@@ -1,7 +1,7 @@
package cn.keking.service;
import cn.keking.model.FileAttribute;
import org.artofsolving.jodconverter.OfficeDocumentConverter;
import org.jodconverter.core.office.OfficeException;
import org.jodconverter.local.JodConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@@ -15,30 +15,23 @@ import java.io.File;
public class OfficeToPdfService {
private final static Logger logger = LoggerFactory.getLogger(OfficeToPdfService.class);
private final OfficePluginManager officePluginManager;
public OfficeToPdfService(OfficePluginManager officePluginManager) {
this.officePluginManager = officePluginManager;
}
public void openOfficeToPDF(String inputFilePath, String outputFilePath, FileAttribute fileAttribute) {
office2pdf(inputFilePath, outputFilePath, fileAttribute);
public void openOfficeToPDF(String inputFilePath, String outputFilePath) throws OfficeException {
office2pdf(inputFilePath, outputFilePath);
}
public static void converterFile(File inputFile, String outputFilePath_end, OfficeDocumentConverter converter, FileAttribute fileAttribute) {
public static void converterFile(File inputFile, String outputFilePath_end) throws OfficeException {
File outputFile = new File(outputFilePath_end);
// 假如目标路径不存在,则新建该路径
if (!outputFile.getParentFile().exists() && !outputFile.getParentFile().mkdirs()) {
logger.error("创建目录【{}】失败,请检查目录权限!",outputFilePath_end);
}
converter.convert(inputFile, outputFile, fileAttribute.toFileProperties());
JodConverter.convert(inputFile).to(outputFile).execute();
}
public void office2pdf(String inputFilePath, String outputFilePath, FileAttribute fileAttribute) {
OfficeDocumentConverter converter = officePluginManager.getDocumentConverter();
public void office2pdf(String inputFilePath, String outputFilePath) throws OfficeException {
if (null != inputFilePath) {
File inputFile = new File(inputFilePath);
// 判断目标文件路径是否为空
@@ -47,12 +40,12 @@ public class OfficeToPdfService {
String outputFilePath_end = getOutputFilePath(inputFilePath);
if (inputFile.exists()) {
// 找不到源文件, 则返回
converterFile(inputFile, outputFilePath_end, converter, fileAttribute);
converterFile(inputFile, outputFilePath_end);
}
} else {
if (inputFile.exists()) {
// 找不到源文件, 则返回
converterFile(inputFile, outputFilePath, converter, fileAttribute);
converterFile(inputFile, outputFilePath);
}
}
}

View File

@@ -1,7 +1,7 @@
package cn.keking.service.cache.impl;
import cn.keking.service.cache.CacheService;
import org.artofsolving.jodconverter.util.ConfigUtils;
import cn.keking.utils.ConfigUtils;
import org.rocksdb.RocksDB;
import org.rocksdb.RocksDBException;
import org.slf4j.Logger;

View File

@@ -5,10 +5,10 @@ import cn.keking.model.FileAttribute;
import cn.keking.model.FileType;
import cn.keking.model.ReturnResponse;
import cn.keking.service.FilePreview;
import cn.keking.utils.ConfigUtils;
import cn.keking.utils.DownloadUtils;
import cn.keking.service.FileHandlerService;
import cn.keking.web.filter.BaseUrlFilter;
import org.artofsolving.jodconverter.util.ConfigUtils;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;

View File

@@ -9,7 +9,7 @@ import cn.keking.service.OfficeToPdfService;
import cn.keking.utils.DownloadUtils;
import cn.keking.utils.OfficeUtils;
import cn.keking.web.filter.BaseUrlFilter;
import org.artofsolving.jodconverter.office.OfficeException;
import org.jodconverter.core.office.OfficeException;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
@@ -83,7 +83,7 @@ public class OfficeFilePreviewImpl implements FilePreview {
isPwdProtectedOffice = OfficeUtils.isPwdProtected(filePath);
}
if (isCached == false) {
if (!isCached) {
// 没有缓存执行转换逻辑
if (isPwdProtectedOffice && !StringUtils.hasLength(filePassword)) {
// 加密文件需要密码
@@ -92,9 +92,9 @@ public class OfficeFilePreviewImpl implements FilePreview {
} else {
if (StringUtils.hasText(outFilePath)) {
try {
officeToPdfService.openOfficeToPDF(filePath, outFilePath, fileAttribute);
officeToPdfService.openOfficeToPDF(filePath, outFilePath);
} catch (OfficeException e) {
if (isPwdProtectedOffice && OfficeUtils.isCompatible(filePath, filePassword) == false) {
if (isPwdProtectedOffice && !OfficeUtils.isCompatible(filePath, filePassword)) {
// 加密文件密码错误,提示重新输入
model.addAttribute("needFilePassword", true);
model.addAttribute("filePasswordError", true);

View File

@@ -0,0 +1,99 @@
package cn.keking.utils;
import java.io.File;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
/**
* @author : kl
**/
public class ConfigUtils {
private static final String MAIN_DIRECTORY_NAME = "server";
public static String getHomePath() {
String userDir = System.getenv("KKFILEVIEW_BIN_FOLDER");
if (userDir == null) {
userDir = System.getProperty("user.dir");
}
if (userDir.endsWith("bin")) {
userDir = userDir.substring(0, userDir.length() - 4);
} else {
String separator = File.separator;
if (userDir.endsWith(MAIN_DIRECTORY_NAME)) {
userDir = userDir + separator + "src" + separator + "main";
} else {
userDir = userDir + separator + MAIN_DIRECTORY_NAME + separator + "src" + separator + "main";
}
}
return userDir;
}
// 获取环境变量,如果找不到则返回默认值
@SuppressWarnings("SameParameterValue")
private static String getEnvOrDefault(String key, String def) {
String value = System.getenv(key);
return value == null ? def : value;
}
// 返回参数列表中第一个真实存在的路径,或者 null
private static String firstExists(File... paths) {
for (File path : paths) {
if (path.exists()) {
return path.getAbsolutePath();
}
}
return null;
}
public static String getUserDir() {
String userDir = System.getProperty("user.dir");
String binFolder = getEnvOrDefault("KKFILEVIEW_BIN_FOLDER", userDir);
File pluginPath = new File(binFolder);
// 如果指定了 bin 或其父目录,则返回父目录
if (new File(pluginPath, "bin").exists()) {
return pluginPath.getAbsolutePath();
} else if (pluginPath.exists() && pluginPath.getName().equals("bin")) {
return pluginPath.getParentFile().getAbsolutePath();
} else {
return firstExists(new File(pluginPath, MAIN_DIRECTORY_NAME),
new File(pluginPath.getParentFile(), MAIN_DIRECTORY_NAME));
}
}
public static String getCustomizedConfigPath() {
String homePath = getHomePath();
String separator = java.io.File.separator;
return homePath + separator + "config" + separator + "application.properties";
}
public synchronized static void restorePropertiesFromEnvFormat(Properties properties) {
Iterator<Map.Entry<Object, Object>> iterator = properties.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Object, Object> entry = iterator.next();
String key = entry.getKey().toString();
String value = entry.getValue().toString();
if (value.trim().startsWith("${") && value.trim().endsWith("}")) {
int beginIndex = value.indexOf(":");
if (beginIndex < 0) {
beginIndex = value.length() - 1;
}
int endIndex = value.length() - 1;
String envKey = value.substring(2, beginIndex);
String envValue = System.getenv(envKey);
if (envValue == null || "".equals(envValue.trim())) {
value = value.substring(beginIndex + 1, endIndex);
} else {
value = envValue;
}
properties.setProperty(key, value);
}
}
}
}

View File

@@ -0,0 +1,111 @@
package cn.keking.utils;
import org.jodconverter.core.util.OSUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Properties;
import java.util.stream.Stream;
/**
* @author chenjh
* @since 2022-12-15
*/
public class LocalOfficeUtils {
public static final String OFFICE_HOME_KEY = "office.home";
public static final String DEFAULT_OFFICE_HOME_VALUE = "default";
private static final String EXECUTABLE_DEFAULT = "program/soffice.bin";
private static final String EXECUTABLE_MAC = "program/soffice";
private static final String EXECUTABLE_MAC_41 = "MacOS/soffice";
private static final String EXECUTABLE_WINDOWS = "program/soffice.exe";
public static File getDefaultOfficeHome() {
Properties properties = new Properties();
String customizedConfigPath = ConfigUtils.getCustomizedConfigPath();
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(customizedConfigPath));
properties.load(bufferedReader);
ConfigUtils.restorePropertiesFromEnvFormat(properties);
} catch (Exception ignored) {}
String officeHome = properties.getProperty(OFFICE_HOME_KEY);
if (officeHome != null && !DEFAULT_OFFICE_HOME_VALUE.equals(officeHome)) {
return new File(officeHome);
}
if (OSUtils.IS_OS_WINDOWS) {
String userDir = ConfigUtils.getUserDir();
// Try to find the most recent version of LibreOffice or OpenOffice,
// starting with the 64-bit version. %ProgramFiles(x86)% on 64-bit
// machines; %ProgramFiles% on 32-bit ones
final String programFiles64 = System.getenv("ProgramFiles");
final String programFiles32 = System.getenv("ProgramFiles(x86)");
return findOfficeHome(EXECUTABLE_WINDOWS,
userDir + File.separator + "windows-office",
programFiles32 + File.separator + "LibreOffice",
programFiles64 + File.separator + "LibreOffice 7",
programFiles32 + File.separator + "LibreOffice 7",
programFiles64 + File.separator + "LibreOffice 6",
programFiles32 + File.separator + "LibreOffice 6",
programFiles64 + File.separator + "LibreOffice 5",
programFiles32 + File.separator + "LibreOffice 5",
programFiles64 + File.separator + "LibreOffice 4",
programFiles32 + File.separator + "LibreOffice 4",
programFiles32 + File.separator + "OpenOffice 4",
programFiles64 + File.separator + "LibreOffice 3",
programFiles32 + File.separator + "LibreOffice 3",
programFiles32 + File.separator + "OpenOffice.org 3");
} else if (OSUtils.IS_OS_MAC) {
File homeDir = findOfficeHome(EXECUTABLE_MAC_41,
"/Applications/LibreOffice.app/Contents",
"/Applications/OpenOffice.app/Contents",
"/Applications/OpenOffice.org.app/Contents");
if (homeDir == null) {
homeDir = findOfficeHome(EXECUTABLE_MAC,
"/Applications/LibreOffice.app/Contents",
"/Applications/OpenOffice.app/Contents",
"/Applications/OpenOffice.org.app/Contents");
}
return homeDir;
} else {
// Linux or other *nix variants
return findOfficeHome(EXECUTABLE_DEFAULT,
"/opt/libreoffice6.0",
"/opt/libreoffice6.1",
"/opt/libreoffice6.2",
"/opt/libreoffice6.3",
"/opt/libreoffice6.4",
"/opt/libreoffice7.0",
"/opt/libreoffice7.1",
"/opt/libreoffice7.2",
"/opt/libreoffice7.3",
"/opt/libreoffice7.4",
"/opt/libreoffice7.5",
"/usr/lib64/libreoffice",
"/usr/lib/libreoffice",
"/usr/local/lib64/libreoffice",
"/usr/local/lib/libreoffice",
"/opt/libreoffice",
"/usr/lib64/openoffice",
"/usr/lib64/openoffice.org3",
"/usr/lib64/openoffice.org",
"/usr/lib/openoffice",
"/usr/lib/openoffice.org3",
"/usr/lib/openoffice.org",
"/opt/openoffice4",
"/opt/openoffice.org3");
}
}
private static File findOfficeHome(final String executablePath, final String... homePaths) {
return Stream.of(homePaths)
.filter(homePath -> Files.isRegularFile(Paths.get(homePath, executablePath)))
.findFirst()
.map(File::new)
.orElse(null);
}
}

View File

@@ -3,7 +3,7 @@ package cn.keking.web.filter;
import cn.keking.config.ConfigConstants;
import cn.keking.utils.WebUtils;
import io.mola.galimatias.GalimatiasParseException;
import org.artofsolving.jodconverter.util.PlatformUtils;
import org.jodconverter.core.util.OSUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
@@ -63,7 +63,7 @@ public class TrustDirFilter implements Filter {
URL url = WebUtils.normalizedURL(urlPath);
if ("file".equals(url.getProtocol().toLowerCase(Locale.ROOT))) {
String filePath = URLDecoder.decode(url.getPath(), StandardCharsets.UTF_8.name());
if (PlatformUtils.isWindows()) {
if (OSUtils.IS_OS_WINDOWS) {
filePath = filePath.replaceAll("/", "\\\\");
}
return filePath.startsWith(ConfigConstants.getFileDir()) || filePath.startsWith(ConfigConstants.getLocalPreviewDir());