diff --git a/server/pom.xml b/server/pom.xml index ddcfcd85..76d1123f 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -99,6 +99,11 @@ ${xdocreport.version} + + org.apache.httpcomponents + httpclient + 4.4 + diff --git a/server/src/main/java/cn/keking/service/FileHandlerService.java b/server/src/main/java/cn/keking/service/FileHandlerService.java index 9663cddd..146310f4 100644 --- a/server/src/main/java/cn/keking/service/FileHandlerService.java +++ b/server/src/main/java/cn/keking/service/FileHandlerService.java @@ -421,7 +421,7 @@ public class FileHandlerService implements InitializingBean { public static String getSubString(String str, String posStr) { return str.substring(str.indexOf(posStr) + posStr.length()); } - + /** * 获取文件属性 * diff --git a/server/src/main/java/cn/keking/utils/DownloadUtils.java b/server/src/main/java/cn/keking/utils/DownloadUtils.java index 91a0fae4..5f8914bf 100644 --- a/server/src/main/java/cn/keking/utils/DownloadUtils.java +++ b/server/src/main/java/cn/keking/utils/DownloadUtils.java @@ -6,23 +6,22 @@ import cn.keking.model.ReturnResponse; import com.fasterxml.jackson.databind.ObjectMapper; import io.mola.galimatias.GalimatiasParseException; import org.apache.commons.io.FileUtils; +import org.apache.http.client.HttpClient; +import org.apache.http.impl.client.DefaultRedirectStrategy; +import org.apache.http.impl.client.HttpClientBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; -import org.springframework.http.client.SimpleClientHttpRequestFactory; -import org.springframework.util.ObjectUtils; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.util.StringUtils; import org.springframework.web.client.RequestCallback; -import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; -import java.net.URI; import java.net.URL; -import java.net.URLEncoder; import java.util.Arrays; import java.util.Map; import java.util.UUID; @@ -41,6 +40,7 @@ public class DownloadUtils { private static final String URL_PARAM_FTP_PASSWORD = "ftp.password"; private static final String URL_PARAM_FTP_CONTROL_ENCODING = "ftp.control.encoding"; private static final RestTemplate restTemplate = new RestTemplate(); + private static final HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); private static final ObjectMapper mapper = new ObjectMapper(); @@ -90,12 +90,12 @@ public class DownloadUtils { if (!fileAttribute.getSkipDownLoad()) { if (isHttpUrl(url)) { File realFile = new File(realPath); - SimpleClientHttpRequestFactory httpFactory = new SimpleClientHttpRequestFactory(); - //连接超时10秒,默认无限制,单位:毫秒 - httpFactory.setConnectTimeout(60 * 1000); - //读取超时5秒,默认无限限制,单位:毫秒 - httpFactory.setReadTimeout(60 * 1000); - restTemplate.setRequestFactory(httpFactory); + factory.setConnectionRequestTimeout(2000); //设置超时时间 + factory.setConnectTimeout(10000); + factory.setReadTimeout(72000); + HttpClient httpClient = HttpClientBuilder.create().setRedirectStrategy(new DefaultRedirectStrategy()).build(); + factory.setHttpClient(httpClient); //加入重定向方法 + restTemplate.setRequestFactory(factory); RequestCallback requestCallback = request -> { request.getHeaders().setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL)); String proxyAuthorization = fileAttribute.getKkProxyAuthorization(); diff --git a/server/src/main/java/cn/keking/utils/RarUtils.java b/server/src/main/java/cn/keking/utils/RarUtils.java index a08c1ce6..1a863fe8 100644 --- a/server/src/main/java/cn/keking/utils/RarUtils.java +++ b/server/src/main/java/cn/keking/utils/RarUtils.java @@ -75,15 +75,20 @@ public class RarUtils { public static boolean judge(char c){ return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'); } + public static String specialSymbols(String str) { + //去除压缩包文件字符串中特殊符号 + // Pattern p = Pattern.compile("\\s|\\+|#|&|=|\\p{P}"); + String regEx="[`+=~&']"; + Pattern p = Pattern.compile(regEx); + Matcher m = p.matcher(str); + return m.replaceAll(""); + } + public static boolean isMessyCode(String strName) { //去除字符串中的空格 制表符 换行 回车 - Pattern p = Pattern.compile("\\s*|\t*|\r*|\n*"); - Matcher m = p.matcher(strName); - String after = m.replaceAll("").replaceAll("\\+", "").replaceAll("#", "").replaceAll("&", ""); - //去除字符串中的标点符号 - String temp = after.replaceAll("\\p{P}", ""); + strName = specialSymbols(strName).replaceAll("\\p{P}", ""); //处理之后转换成字符数组 - char[] ch = temp.trim().toCharArray(); + char[] ch = strName.trim().toCharArray(); for (char c : ch) { //判断是否是数字或者英文字符 if (!judge(c)) { diff --git a/server/src/main/java/cn/keking/utils/WebUtils.java b/server/src/main/java/cn/keking/utils/WebUtils.java index 3cb01d9f..9387be72 100644 --- a/server/src/main/java/cn/keking/utils/WebUtils.java +++ b/server/src/main/java/cn/keking/utils/WebUtils.java @@ -5,7 +5,6 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.Base64Utils; -import org.springframework.util.ObjectUtils; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.util.HtmlUtils; @@ -74,15 +73,20 @@ public class WebUtils { */ public static String urlEncoderencode(String urlStr) { - String fullFileName = getUrlParameterReg(urlStr, "fullfilename"); //获取文件名 - if (!ObjectUtils.isEmpty(fullFileName)) { //判断是否启用了 流接入方法 - urlStr = clearFullfilenameParam(urlStr); //去掉流接入 拼接命令 + String fullFileName = getUrlParameterReg(urlStr, "fullfilename"); //获取流文件名 + if (org.springframework.util.StringUtils.hasText(fullFileName)) { + // 移除fullfilename参数 + urlStr = clearFullfilenameParam(urlStr); + } else { + fullFileName = getFileNameFromURL(urlStr); //获取文件名 + } - try { - urlStr = URLEncoder.encode(urlStr, "UTF-8").replaceAll("\\+", "%20"); - urlStr = urlStr.replaceAll("%3A", ":").replaceAll("%2F", "/").replaceAll("%3F", "?").replaceAll("%26", "&"); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); + if (!UrlEncoderUtils.hasUrlEncoded(fullFileName)) { //判断文件名是否转义 + try { + urlStr = URLEncoder.encode(urlStr, "UTF-8").replaceAll("\\+", "%20").replaceAll("%3A", ":").replaceAll("%2F", "/").replaceAll("%3F", "?").replaceAll("%26", "&"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } } return urlStr; } 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 809aeaef..f100600b 100644 --- a/server/src/main/java/cn/keking/web/controller/OnlinePreviewController.java +++ b/server/src/main/java/cn/keking/web/controller/OnlinePreviewController.java @@ -8,28 +8,33 @@ import cn.keking.service.cache.CacheService; import cn.keking.service.impl.OtherFilePreviewImpl; import cn.keking.utils.KkFileUtils; import cn.keking.utils.WebUtils; +import com.fasterxml.jackson.databind.ObjectMapper; import fr.opensagres.xdocreport.core.io.IOUtils; -import io.mola.galimatias.GalimatiasParseException; import org.apache.commons.codec.binary.Base64; +import org.apache.http.client.HttpClient; +import org.apache.http.impl.client.DefaultRedirectStrategy; +import org.apache.http.impl.client.HttpClientBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; 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.ResponseBody; +import org.springframework.web.client.RequestCallback; +import org.springframework.web.client.RestTemplate; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.HttpURLConnection; import java.net.URL; -import java.net.URLDecoder; -import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.List; +import java.util.Map; import static cn.keking.service.FilePreview.PICTURE_FILE_PREVIEW_PAGE; @@ -46,6 +51,9 @@ public class OnlinePreviewController { private final CacheService cacheService; private final FileHandlerService fileHandlerService; private final OtherFilePreviewImpl otherFilePreview; + private static final RestTemplate restTemplate = new RestTemplate(); + private static final HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); + private static final ObjectMapper mapper = new ObjectMapper(); public OnlinePreviewController(FilePreviewFactory filePreviewFactory, FileHandlerService fileHandlerService, CacheService cacheService, OtherFilePreviewImpl otherFilePreview) { this.previewFactory = filePreviewFactory; @@ -106,83 +114,53 @@ public class OnlinePreviewController { * @param response response */ @GetMapping("/getCorsFile") - public void getCorsFile(String urlPath, HttpServletResponse response) throws IOException { + public void getCorsFile(String urlPath, HttpServletResponse response,FileAttribute fileAttribute) throws IOException { + URL url; try { urlPath = WebUtils.decodeUrl(urlPath); + url = WebUtils.normalizedURL(urlPath); } catch (Exception ex) { logger.error(String.format(BASE64_DECODE_ERROR_MSG, urlPath),ex); return; } - HttpURLConnection urlcon = null; - InputStream inputStream = null; - String urlStr; assert urlPath != null; if (!urlPath.toLowerCase().startsWith("http") && !urlPath.toLowerCase().startsWith("https") && !urlPath.toLowerCase().startsWith("ftp")) { logger.info("读取跨域文件异常,可能存在非法访问,urlPath:{}", urlPath); return; } - logger.info("下载跨域pdf文件url:{}", urlPath); - if (!urlPath.toLowerCase().startsWith("ftp:")){ + InputStream inputStream = null; + logger.info("读取跨域pdf文件url:{}", urlPath); + if (!urlPath.toLowerCase().startsWith("ftp:")) { + factory.setConnectionRequestTimeout(2000); + factory.setConnectTimeout(10000); + factory.setReadTimeout(72000); + HttpClient httpClient = HttpClientBuilder.create().setRedirectStrategy(new DefaultRedirectStrategy()).build(); + factory.setHttpClient(httpClient); + restTemplate.setRequestFactory(factory); + RequestCallback requestCallback = request -> { + request.getHeaders().setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL)); + String proxyAuthorization = fileAttribute.getKkProxyAuthorization(); + if(StringUtils.hasText(proxyAuthorization)){ + Map proxyAuthorizationMap = mapper.readValue(proxyAuthorization, Map.class); + proxyAuthorizationMap.forEach((key, value) -> request.getHeaders().set(key, value)); + } + }; try { - URL url = WebUtils.normalizedURL(urlPath); - urlcon=(HttpURLConnection)url.openConnection(); - urlcon.setConnectTimeout(30000); - urlcon.setReadTimeout(30000); - urlcon.setInstanceFollowRedirects(false); - int responseCode = urlcon.getResponseCode(); - if ( responseCode == 403 || responseCode == 500) { //403 500 - logger.error("读取跨域文件异常,url:{},错误:{}", urlPath,responseCode); - return ; - } - if (responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_MOVED_TEMP) { //301 302 - url =new URL(urlcon.getHeaderField("Location")); - urlcon=(HttpURLConnection)url.openConnection(); - } if (responseCode == 404 ) { //404 - try { - urlStr = URLDecoder.decode(urlPath, StandardCharsets.UTF_8.name()); - urlStr = URLDecoder.decode(urlStr, StandardCharsets.UTF_8.name()); - url = WebUtils.normalizedURL(urlStr); - urlcon=(HttpURLConnection)url.openConnection(); - urlcon.setConnectTimeout(30000); - urlcon.setReadTimeout(30000); - urlcon.setInstanceFollowRedirects(false); - responseCode = urlcon.getResponseCode(); - if (responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_MOVED_TEMP) { //301 302 - url =new URL(urlcon.getHeaderField("Location")); - } - if(responseCode == 404 ||responseCode == 403 || responseCode == 500 ){ - logger.error("读取跨域文件异常,url:{},错误:{}", urlPath,responseCode); - return ; - } - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - }finally { - assert urlcon != null; - urlcon.disconnect(); - } - } - 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); - } finally { - assert urlcon != null; - urlcon.disconnect(); - IOUtils.closeQuietly(inputStream); + restTemplate.execute(url.toURI(), HttpMethod.GET, requestCallback, fileResponse -> { + IOUtils.copy(fileResponse.getBody(), response.getOutputStream()); + return null; + }); + } catch (Exception e) { + System.out.println(e); } - } else { + }else{ try { - URL url = WebUtils.normalizedURL(urlPath); if(urlPath.contains(".svg")) { response.setContentType("image/svg+xml"); } inputStream = (url).openStream(); IOUtils.copy(inputStream, response.getOutputStream()); - } catch (IOException | GalimatiasParseException e) { + } catch (IOException e) { logger.error("读取跨域文件异常,url:{}", urlPath); } finally { IOUtils.closeQuietly(inputStream); diff --git a/server/src/main/resources/web/compress.ftl b/server/src/main/resources/web/compress.ftl index d0b5c2fe..4c588cd1 100644 --- a/server/src/main/resources/web/compress.ftl +++ b/server/src/main/resources/web/compress.ftl @@ -51,7 +51,7 @@ }; function chooseNode(event, treeId, treeNode) { if (!treeNode.isParent) { - var path = '${baseUrl}' + treeNode.id + "?kkCompressfileKey=" + '${fileTree}'+"&kkCompressfilepath=" + treeNode.id+"&fullfilename="+treeNode.name; + var path = '${baseUrl}'+ treeNode.id.split("/").map(name=>encodeURIComponent(name)).join("/") + "?kkCompressfileKey=" + encodeURIComponent('${fileTree}')+"&kkCompressfilepath=" + encodeURIComponent(treeNode.id)+"&fullfilename="+encodeURIComponent(treeNode.name); location.href = "${baseUrl}onlinePreview?url=" + encodeURIComponent(Base64.encode(path)); } }