diff --git a/pom.xml b/pom.xml
index c4148ef5da8f187b6f4281f93a3ddabad01d6564..b7856d4346eb7dcee5f32cc11c328d9ae87757e2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -35,6 +35,7 @@
3.1
23.1
1.70
+ 1.2.83
1.2
3.6
diff --git a/server/pom.xml b/server/pom.xml
index 23dc67d5ddb90d70780e9da490c79fad00f4c51b..7b2d38258c287e5fc8b745fcddd74ba76e0f6e6f 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -277,7 +277,16 @@
system
${pom.basedir}/lib/jai_codec-1.1.3.jar
-
+
+ org.apache.httpcomponents
+ httpclient
+
+
+
+ com.alibaba
+ fastjson
+ ${fastjson.version}
+
org.springframework.boot
diff --git a/server/src/main/config/application.properties b/server/src/main/config/application.properties
index 392b7a27b3248dad215a0df1ed33139d4c5bf665..a24e69e727f2f31bac502d3315e870eb28870812 100644
--- a/server/src/main/config/application.properties
+++ b/server/src/main/config/application.properties
@@ -53,6 +53,15 @@ cache.clean.cron = ${KK_CACHE_CLEAN_CRON:0 0 3 * * ?}
#提供预览服务的地址,默认从请求url读,如果使用nginx等反向代理,需要手动设置
#base.url = https://file.keking.cn
base.url = ${KK_BASE_URL:default}
+#提供预览服务的办公网络地址,默认从请求url读,如果使用nginx等反向代理,需要手动设置
+base.url.office = ${KK_BASE_URL_OFFICE:default}
+#提供预览服务的互联网络地址,默认从请求url读,如果使用nginx等反向代理,需要手动设置
+base.url.out = ${KK_BASE_URL_OUT:default}
+#提供预览服务的办公网络地址,默认从请求url读,如果使用nginx等反向代理,需要手动设置
+#base.file.url.office = http://113.140.95.222:60533
+base.file.url.office = ${KK_BASE_FILE_URL_OFFICE:default}
+#提供预览服务的互联网络地址,默认从请求url读,如果使用nginx等反向代理,需要手动设置
+base.file.url.out = ${KK_BASE_FILE_URL_OUT:default}
#信任站点,多个用','隔开,设置了之后,会限制只能预览来自信任站点列表的文件,默认不限制
#trust.host = kkview.cn
diff --git a/server/src/main/java/cn/keking/config/ConfigConstants.java b/server/src/main/java/cn/keking/config/ConfigConstants.java
index 7528f386be394a3fa766b5901d198c85533c8d8e..b65cb969900670f66b576849cf6c32480a956a60 100644
--- a/server/src/main/java/cn/keking/config/ConfigConstants.java
+++ b/server/src/main/java/cn/keking/config/ConfigConstants.java
@@ -32,6 +32,10 @@ public class ConfigConstants {
private static String ftpPassword;
private static String ftpControlEncoding;
private static String baseUrl;
+ private static String baseUrlOffice;
+ private static String baseUrlOut;
+ private static String baseFileUrlOffice;
+ private static String baseFileUrlOut;
private static String fileDir = ConfigUtils.getHomePath() + File.separator + "file" + File.separator;
private static String localPreviewDir;
private static CopyOnWriteArraySet trustHostSet;
@@ -139,6 +143,7 @@ public class ConfigConstants {
public void setMediaConvertDisable(String mediaConvertDisable) {
setMediaConvertDisableValue(mediaConvertDisable);
}
+
public static void setMediaConvertDisableValue(String mediaConvertDisable) {
ConfigConstants.mediaConvertDisable = mediaConvertDisable;
}
@@ -208,6 +213,56 @@ public class ConfigConstants {
ConfigConstants.baseUrl = baseUrl;
}
+ public static String getBaseUrlOffice() {
+ return baseUrlOffice;
+ }
+
+ @Value("${base.url.office:default}")
+ public void setBaseUrlOffice(String baseUrlOffice) {
+ setBaseUrlOfficeValue(baseUrlOffice);
+ }
+
+ public static void setBaseUrlOfficeValue(String baseUrlOffice) {
+ ConfigConstants.baseUrlOffice = baseUrlOffice;
+ }
+
+ public static String getBaseUrlOut() {
+ return baseUrlOut;
+ }
+
+ @Value("${base.url.out:default}")
+ public void setBaseUrlOut(String baseUrlOut) {
+ setBaseUrlOutValue(baseUrlOut);
+ }
+ public static String getBaseFileUrlOffice() {
+ return baseFileUrlOffice;
+ }
+
+ @Value("${base.file.url.office:default}")
+ public void setBaseFileUrlOffice(String baseFileUrlOffice) {
+ setBaseFileUrlOfficeValue(baseFileUrlOffice);
+ }
+
+ public static void setBaseFileUrlOfficeValue(String baseFileUrlOffice) {
+ ConfigConstants.baseFileUrlOffice = baseFileUrlOffice;
+ }
+
+ public static String getBaseFileUrlOut() {
+ return baseFileUrlOut;
+ }
+
+ @Value("${base.file.url.out:default}")
+ public void setBaseFileUrlOut(String baseFileUrlOut) {
+ setBaseFileUrlOutValue(baseFileUrlOut);
+ }
+
+ public static void setBaseFileUrlOutValue(String baseFileUrlOut) {
+ ConfigConstants.baseFileUrlOut = baseFileUrlOut;
+ }
+
+ public static void setBaseUrlOutValue(String baseUrlOut) {
+ ConfigConstants.baseUrlOut = baseUrlOut;
+ }
public static String getFileDir() {
return fileDir;
}
@@ -290,6 +345,7 @@ public class ConfigConstants {
public void setPdfOpenFileDisable(String pdfOpenFileDisable) {
setPdfOpenFileDisableValue(pdfOpenFileDisable);
}
+
public static void setPdfOpenFileDisableValue(String pdfOpenFileDisable) {
ConfigConstants.pdfOpenFileDisable = pdfOpenFileDisable;
}
@@ -297,10 +353,12 @@ public class ConfigConstants {
public static String getPdfPrintDisable() {
return pdfPrintDisable;
}
+
@Value("${pdf.print.disable:true}")
public void setPdfPrintDisable(String pdfPrintDisable) {
setPdfPrintDisableValue(pdfPrintDisable);
}
+
public static void setPdfPrintDisableValue(String pdfPrintDisable) {
ConfigConstants.pdfPrintDisable = pdfPrintDisable;
}
@@ -313,6 +371,7 @@ public class ConfigConstants {
public void setPdfDownloadDisable(String pdfDownloadDisable) {
setPdfDownloadDisableValue(pdfDownloadDisable);
}
+
public static void setPdfDownloadDisableValue(String pdfDownloadDisable) {
ConfigConstants.pdfDownloadDisable = pdfDownloadDisable;
}
@@ -320,10 +379,12 @@ public class ConfigConstants {
public static String getPdfBookmarkDisable() {
return pdfBookmarkDisable;
}
+
@Value("${pdf.bookmark.disable:true}")
public void setPdfBookmarkDisable(String pdfBookmarkDisable) {
setPdfBookmarkDisableValue(pdfBookmarkDisable);
}
+
public static void setPdfBookmarkDisableValue(String pdfBookmarkDisable) {
ConfigConstants.pdfBookmarkDisable = pdfBookmarkDisable;
}
@@ -331,10 +392,12 @@ public class ConfigConstants {
public static String getOfficePreviewSwitchDisabled() {
return officePreviewSwitchDisabled;
}
+
@Value("${office.preview.switch.disabled:true}")
public void setOfficePreviewSwitchDisabled(String officePreviewSwitchDisabled) {
ConfigConstants.officePreviewSwitchDisabled = officePreviewSwitchDisabled;
}
+
public static void setOfficePreviewSwitchDisabledValue(String officePreviewSwitchDisabled) {
ConfigConstants.officePreviewSwitchDisabled = officePreviewSwitchDisabled;
}
@@ -369,16 +432,20 @@ public class ConfigConstants {
public static String getBeiAn() {
return beiAn;
}
+
@Value("${beiAn:无}")
public void setBeiAn(String beiAn) {
setBeiAnValue(beiAn);
}
+
public static void setBeiAnValue(String beiAn) {
ConfigConstants.beiAn = beiAn;
}
+
public static String[] getProhibit() {
return prohibit;
}
+
@Value("${prohibit:exe,dll}")
public void setProhibit(String prohibit) {
String[] prohibitArr = prohibit.split(",");
@@ -388,13 +455,16 @@ public class ConfigConstants {
public static void setProhibitValue(String[] prohibit) {
ConfigConstants.prohibit = prohibit;
}
+
public static String maxSize() {
return size;
}
+
@Value("${spring.servlet.multipart.max-file-size:500MB}")
public void setSize(String size) {
setSizeValue(size);
}
+
public static void setSizeValue(String size) {
ConfigConstants.size = size;
}
@@ -402,10 +472,12 @@ public class ConfigConstants {
public static String getPassword() {
return password;
}
+
@Value("${sc.password:123456}")
public void setPassword(String password) {
setPasswordValue(password);
}
+
public static void setPasswordValue(String password) {
ConfigConstants.password = password;
}
@@ -414,10 +486,12 @@ public class ConfigConstants {
public static int getPdf2JpgDpi() {
return pdf2JpgDpi;
}
+
@Value("${pdf.picture.size:105}")
public void pdf2JpgDpi(int pdf2JpgDpi) {
setPdf2JpgDpiValue(pdf2JpgDpi);
}
+
public static void setPdf2JpgDpiValue(int pdf2JpgDpi) {
ConfigConstants.pdf2JpgDpi = pdf2JpgDpi;
}
diff --git a/server/src/main/java/cn/keking/exception/CallBackException.java b/server/src/main/java/cn/keking/exception/CallBackException.java
new file mode 100644
index 0000000000000000000000000000000000000000..08c78dc10bf5008593f6d41c489fc33b636599e1
--- /dev/null
+++ b/server/src/main/java/cn/keking/exception/CallBackException.java
@@ -0,0 +1,4 @@
+package cn.keking.exception;
+
+public class CallBackException extends RuntimeException{
+}
diff --git a/server/src/main/java/cn/keking/service/FileConvertQueueTask.java b/server/src/main/java/cn/keking/service/FileConvertQueueTask.java
index e5d6248535ae28b75fb4d07e779c58333a8f9edc..d86b89a2428cad9327b9c7d75121f02764fd130e 100644
--- a/server/src/main/java/cn/keking/service/FileConvertQueueTask.java
+++ b/server/src/main/java/cn/keking/service/FileConvertQueueTask.java
@@ -1,8 +1,11 @@
package cn.keking.service;
+import cn.keking.exception.CallBackException;
import cn.keking.model.FileAttribute;
import cn.keking.model.FileType;
import cn.keking.service.cache.CacheService;
+import cn.keking.utils.HttpUtils;
+import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@@ -58,6 +61,11 @@ public class FileConvertQueueTask {
try {
url = cacheService.takeQueueTask();
if (url != null) {
+ String callbackUrl = null;
+ if (url.contains("callbackUrl")) {
+ callbackUrl = url.split("callbackUrl")[1];
+ url = url.split("callbackUrl")[0];
+ }
FileAttribute fileAttribute = fileHandlerService.getFileAttribute(url, null);
FileType fileType = fileAttribute.getType();
logger.info("正在处理预览转换任务,url:{},预览类型:{}", url, fileType);
@@ -67,6 +75,8 @@ public class FileConvertQueueTask {
} else {
logger.info("预览类型无需处理,url:{},预览类型:{}", url, fileType);
}
+ String finalCallbackUrl = callbackUrl;
+ new Thread(() -> callback(finalCallbackUrl)).start();
}
} catch (Exception e) {
try {
@@ -80,9 +90,34 @@ public class FileConvertQueueTask {
}
}
- public boolean isNeedConvert(FileType fileType) {
- return fileType.equals(FileType.COMPRESS) || fileType.equals(FileType.OFFICE) || fileType.equals(FileType.CAD);
+ private void callback(String callbackUrl) {
+ if (null != callbackUrl && !callbackUrl.equals("")) {
+ //http回调通知
+ try {
+ JSONObject jsonObject = HttpUtils.sendGet(callbackUrl);
+ if (null != jsonObject && jsonObject.getInteger("code") == 200) {
+ logger.info("成功回调通知地址:" + callbackUrl);
+ } else {
+ logger.error("失败回调通知地址:" + callbackUrl);
+ }
+ } catch (CallBackException e) {
+ try {
+ Thread.sleep(1000 * 10);
+ } catch (InterruptedException ex) {
+ throw new RuntimeException(ex);
+ }
+ JSONObject jsonObject1 = HttpUtils.sendGet(callbackUrl);
+ if (null != jsonObject1 && jsonObject1.getInteger("code") == 200) {
+ logger.info("成功回调通知地址:" + callbackUrl);
+ } else {
+ logger.error("失败回调通知地址:" + callbackUrl);
+ }
+ }
+ }
+ }
+ public boolean isNeedConvert(FileType fileType) {
+ return fileType.equals(FileType.COMPRESS) || fileType.equals(FileType.PDF) || fileType.equals(FileType.OFFICE) || fileType.equals(FileType.CAD);
}
}
diff --git a/server/src/main/java/cn/keking/utils/HttpUtils.java b/server/src/main/java/cn/keking/utils/HttpUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..8e5ad3605ec997e88f88953b88e8fb79915f8140
--- /dev/null
+++ b/server/src/main/java/cn/keking/utils/HttpUtils.java
@@ -0,0 +1,51 @@
+package cn.keking.utils;
+
+import cn.keking.exception.CallBackException;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.util.EntityUtils;
+
+import java.io.IOException;
+
+/**
+ * @ClassName: HttpUtils
+ * @Description:
+ * @Author: wangf
+ * @Date: 2019/11/12 0012 14:38
+ * @Version: 1.0
+ **/
+
+public class HttpUtils {
+
+ /**
+ * 发送HttpGet请求
+ *
+ * @param url
+ * @return */
+ public static JSONObject sendGet(String url) {
+ CloseableHttpClient client = HttpClientBuilder.create().build();
+ URIBuilder uriBuilder = null;
+ CloseableHttpResponse response = null;
+ String data = "";
+ try {
+ uriBuilder = new URIBuilder(url);
+ response = client.execute(new HttpGet(uriBuilder.build()));
+ data = EntityUtils.toString(response.getEntity());
+ }catch (Exception e){
+ throw new CallBackException();
+ }finally {
+ if (response != null) {
+ try {
+ response.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return JSONObject.parseObject(data);
+ }
+}
diff --git a/server/src/main/java/cn/keking/web/controller/OnlinePreviewController.java b/server/src/main/java/cn/keking/web/controller/OnlinePreviewController.java
index ba11e2168e631a5722ab3aba329456dff7248b9c..3a8a7b198670cc136811c1b7e1d13c721c9147e3 100644
--- a/server/src/main/java/cn/keking/web/controller/OnlinePreviewController.java
+++ b/server/src/main/java/cn/keking/web/controller/OnlinePreviewController.java
@@ -1,5 +1,6 @@
package cn.keking.web.controller;
+import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute;
import cn.keking.service.FileHandlerService;
import cn.keking.service.FilePreview;
@@ -17,6 +18,7 @@ import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
@@ -51,11 +53,23 @@ public class OnlinePreviewController {
this.otherFilePreview = otherFilePreview;
}
- @GetMapping( "/onlinePreview")
+ @GetMapping("/onlinePreview")
public String onlinePreview(String url, Model model, HttpServletRequest req) {
String fileUrl;
try {
fileUrl = WebUtils.decodeUrl(url);
+ assert fileUrl != null;
+ String huanjing = req.getParameter("Huanjing");
+ if (null != huanjing && fileUrl.contains("http")){
+ // 判断环境
+ String[] split = fileUrl.split("lc-data");
+ if (huanjing.equals("office")) {
+ fileUrl = ConfigConstants.getBaseFileUrlOffice()+"/lc-data"+split[1];
+ }
+ if (huanjing.equals("out")) {
+ fileUrl = ConfigConstants.getBaseFileUrlOut()+"/lc-data"+split[1];
+ }
+ }
} catch (Exception ex) {
String errorMsg = String.format(BASE64_DECODE_ERROR_MSG, "url");
return otherFilePreview.notSupportedFile(model, errorMsg);
@@ -67,7 +81,7 @@ public class OnlinePreviewController {
return filePreview.filePreviewHandle(fileUrl, model, fileAttribute);
}
- @GetMapping( "/picturesPreview")
+ @GetMapping("/picturesPreview")
public String picturesPreview(String urls, Model model, HttpServletRequest req) {
String fileUrls;
try {
@@ -86,7 +100,7 @@ public class OnlinePreviewController {
String currentUrl = req.getParameter("currentUrl");
if (StringUtils.hasText(currentUrl)) {
String decodedCurrentUrl = new String(Base64.decodeBase64(currentUrl));
- decodedCurrentUrl = KkFileUtils.htmlEscape(decodedCurrentUrl); // 防止XSS攻击
+ decodedCurrentUrl = KkFileUtils.htmlEscape(decodedCurrentUrl); // 防止XSS攻击
model.addAttribute("currentUrl", decodedCurrentUrl);
} else {
model.addAttribute("currentUrl", imgUrls.get(0));
@@ -106,7 +120,7 @@ public class OnlinePreviewController {
try {
urlPath = WebUtils.decodeUrl(urlPath);
} catch (Exception ex) {
- logger.error(String.format(BASE64_DECODE_ERROR_MSG, urlPath),ex);
+ logger.error(String.format(BASE64_DECODE_ERROR_MSG, urlPath), ex);
return;
}
HttpURLConnection urlcon;
@@ -116,46 +130,46 @@ public class OnlinePreviewController {
return;
}
logger.info("下载跨域pdf文件url:{}", urlPath);
- if (!urlPath.toLowerCase().startsWith("ftp:")){
+ if (!urlPath.toLowerCase().startsWith("ftp:")) {
try {
URL url = WebUtils.normalizedURL(urlPath);
- urlcon=(HttpURLConnection)url.openConnection();
+ urlcon = (HttpURLConnection) url.openConnection();
urlcon.setConnectTimeout(30000);
urlcon.setReadTimeout(30000);
urlcon.setInstanceFollowRedirects(false);
if (urlcon.getResponseCode() == 302 || urlcon.getResponseCode() == 301) {
urlcon.disconnect();
- url =new URL(urlcon.getHeaderField("Location"));
- urlcon=(HttpURLConnection)url.openConnection();
+ url = new URL(urlcon.getHeaderField("Location"));
+ urlcon = (HttpURLConnection) url.openConnection();
}
- if (urlcon.getResponseCode() == 404 || urlcon.getResponseCode() == 403 || urlcon.getResponseCode() == 500 ) {
+ if (urlcon.getResponseCode() == 404 || urlcon.getResponseCode() == 403 || urlcon.getResponseCode() == 500) {
logger.error("读取跨域文件异常,url:{}", urlPath);
- return ;
+ return;
} else {
- if(urlPath.contains( ".svg")) {
+ if (urlPath.contains(".svg")) {
response.setContentType("image/svg+xml");
}
- inputStream=(url).openStream();
+ inputStream = (url).openStream();
IOUtils.copy(inputStream, response.getOutputStream());
urlcon.disconnect();
}
} catch (IOException | GalimatiasParseException e) {
logger.error("读取跨域文件异常,url:{}", urlPath);
- return ;
+ return;
} finally {
IOUtils.closeQuietly(inputStream);
}
} else {
try {
URL url = WebUtils.normalizedURL(urlPath);
- if(urlPath.contains(".svg")) {
+ if (urlPath.contains(".svg")) {
response.setContentType("image/svg+xml");
}
inputStream = (url).openStream();
IOUtils.copy(inputStream, response.getOutputStream());
} catch (IOException | GalimatiasParseException e) {
logger.error("读取跨域文件异常,url:{}", urlPath);
- return ;
+ return;
} finally {
IOUtils.closeQuietly(inputStream);
}
@@ -169,9 +183,14 @@ public class OnlinePreviewController {
*/
@GetMapping("/addTask")
@ResponseBody
- public String addQueueTask(String url) {
+ public String addQueueTask(@RequestParam("url") String url, @RequestParam(value = "callbackUrl", required = false) String callbackUrl) {
logger.info("添加转码队列url:{}", url);
- cacheService.addQueueTask(url);
+ logger.info("回调通知url:{}", callbackUrl);
+ if (null != callbackUrl&&!callbackUrl.equals("")) {
+ cacheService.addQueueTask(url + "callbackUrl" + callbackUrl);
+ } else {
+ cacheService.addQueueTask(url);
+ }
return "success";
}
}
diff --git a/server/src/main/java/cn/keking/web/filter/BaseUrlFilter.java b/server/src/main/java/cn/keking/web/filter/BaseUrlFilter.java
index 96828fd90d00a49d9b31375ace15038f20b23a97..6f188261f4bd789e8ce28a1c5de3fc3d2bc09794 100644
--- a/server/src/main/java/cn/keking/web/filter/BaseUrlFilter.java
+++ b/server/src/main/java/cn/keking/web/filter/BaseUrlFilter.java
@@ -39,6 +39,14 @@ public class BaseUrlFilter implements Filter {
String configBaseUrl = ConfigConstants.getBaseUrl();
final HttpServletRequest servletRequest = (HttpServletRequest) request;
+ // 判断环境
+ String huanjing = servletRequest.getParameter("Huanjing");
+ if (null != huanjing && huanjing.equals("office")) {
+ configBaseUrl = ConfigConstants.getBaseUrlOffice();
+ }
+ if (null != huanjing && huanjing.equals("out")) {
+ configBaseUrl = ConfigConstants.getBaseUrlOut();
+ }
//1、支持通过 http header 中 X-Base-Url 来动态设置 baseUrl 以支持多个域名/项目的共享使用
final String urlInHeader = servletRequest.getHeader("X-Base-Url");
if (StringUtils.isNotEmpty(urlInHeader)) {