diff --git a/server/src/main/java/cn/keking/config/SchedulerCleanConfig.java b/server/src/main/java/cn/keking/config/SchedulerCleanConfig.java index 9817a652..7f808f9e 100644 --- a/server/src/main/java/cn/keking/config/SchedulerCleanConfig.java +++ b/server/src/main/java/cn/keking/config/SchedulerCleanConfig.java @@ -1,7 +1,7 @@ package cn.keking.config; import cn.keking.service.cache.CacheService; -import cn.keking.utils.FileUtils; +import cn.keking.utils.KkFileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; @@ -31,7 +31,7 @@ public class SchedulerCleanConfig { public void clean() { logger.info("Cache clean start"); cacheService.cleanCache(); - FileUtils.deleteDirectory(fileDir); + KkFileUtils.deleteDirectory(fileDir); logger.info("Cache clean end"); } } diff --git a/server/src/main/java/cn/keking/service/CompressFileReader.java b/server/src/main/java/cn/keking/service/CompressFileReader.java index c396e56b..187dd845 100644 --- a/server/src/main/java/cn/keking/service/CompressFileReader.java +++ b/server/src/main/java/cn/keking/service/CompressFileReader.java @@ -2,7 +2,7 @@ package cn.keking.service; import cn.keking.config.ConfigConstants; import cn.keking.model.FileType; -import cn.keking.utils.FileUtils; +import cn.keking.utils.KkFileUtils; import cn.keking.web.filter.BaseUrlFilter; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -48,7 +48,7 @@ public class CompressFileReader { String baseUrl = BaseUrlFilter.getBaseUrl(); String archiveFileName = fileHandlerService.getFileNameFromPath(filePath); try { - ZipFile zipFile = new ZipFile(filePath, FileUtils.getFileEncode(filePath)); + ZipFile zipFile = new ZipFile(filePath, KkFileUtils.getFileEncode(filePath)); Enumeration entries = zipFile.getEntries(); // 排序 entries = sortZipEntries(entries); @@ -382,7 +382,7 @@ public class CompressFileReader { } catch (IOException e) { e.printStackTrace(); } - FileUtils.deleteFileByPath(filePath); + KkFileUtils.deleteFileByPath(filePath); } private void extractZipFile(String childName, InputStream zipFile) { @@ -439,7 +439,7 @@ public class CompressFileReader { } catch (IOException e) { e.printStackTrace(); } - FileUtils.deleteFileByPath(filePath); + KkFileUtils.deleteFileByPath(filePath); } } @@ -468,7 +468,7 @@ public class CompressFileReader { } catch (IOException e) { e.printStackTrace(); } - FileUtils.deleteFileByPath(filePath); + KkFileUtils.deleteFileByPath(filePath); } private void extractRarFile(String childName, FileHeader header, Archive archive) { diff --git a/server/src/main/java/cn/keking/service/FileHandlerService.java b/server/src/main/java/cn/keking/service/FileHandlerService.java index ca072533..d5916b40 100644 --- a/server/src/main/java/cn/keking/service/FileHandlerService.java +++ b/server/src/main/java/cn/keking/service/FileHandlerService.java @@ -4,7 +4,7 @@ import cn.keking.config.ConfigConstants; import cn.keking.model.FileAttribute; import cn.keking.model.FileType; import cn.keking.service.cache.CacheService; -import cn.keking.utils.FileUtils; +import cn.keking.utils.KkFileUtils; import cn.keking.utils.WebUtils; import com.aspose.cad.Color; import com.aspose.cad.fileformats.cad.CadDrawTypeMode; @@ -263,7 +263,7 @@ public class FileHandlerService { if (StringUtils.hasText(fullFileName)) { fileName = fullFileName; type = FileType.typeFromFileName(fullFileName); - suffix = FileUtils.suffixFromFileName(fullFileName); + suffix = KkFileUtils.suffixFromFileName(fullFileName); } else { fileName = WebUtils.getFileNameFromURL(url); type = FileType.typeFromUrl(url); diff --git a/server/src/main/java/cn/keking/service/impl/SimTextFilePreviewImpl.java b/server/src/main/java/cn/keking/service/impl/SimTextFilePreviewImpl.java index f5f31f7f..9004141e 100644 --- a/server/src/main/java/cn/keking/service/impl/SimTextFilePreviewImpl.java +++ b/server/src/main/java/cn/keking/service/impl/SimTextFilePreviewImpl.java @@ -4,6 +4,7 @@ import cn.keking.model.FileAttribute; import cn.keking.model.ReturnResponse; import cn.keking.service.FilePreview; import cn.keking.utils.DownloadUtils; +import cn.keking.utils.KkFileUtils; import org.apache.commons.io.FileUtils; import org.springframework.stereotype.Service; import org.springframework.ui.Model; @@ -11,7 +12,6 @@ import org.springframework.util.Base64Utils; import java.io.File; import java.io.IOException; -import java.nio.charset.StandardCharsets; /** * Created by kl on 2018/1/17. @@ -35,8 +35,9 @@ public class SimTextFilePreviewImpl implements FilePreview { } try { File originFile = new File(response.getContent()); - String xmlString = FileUtils.readFileToString(originFile, StandardCharsets.UTF_8); - model.addAttribute("textData", Base64Utils.encodeToString(xmlString.getBytes(StandardCharsets.UTF_8))); + String charset = KkFileUtils.getFileEncode(originFile); + String xmlString = FileUtils.readFileToString(originFile, charset); + model.addAttribute("textData", Base64Utils.encodeToString(xmlString.getBytes(charset))); } catch (IOException e) { return otherFilePreview.notSupportedFile(model, fileAttribute, e.getLocalizedMessage()); } diff --git a/server/src/main/java/cn/keking/utils/DownloadUtils.java b/server/src/main/java/cn/keking/utils/DownloadUtils.java index 6c48d81c..76f03c50 100644 --- a/server/src/main/java/cn/keking/utils/DownloadUtils.java +++ b/server/src/main/java/cn/keking/utils/DownloadUtils.java @@ -2,17 +2,19 @@ package cn.keking.utils; import cn.keking.config.ConfigConstants; import cn.keking.model.FileAttribute; -import cn.keking.model.FileType; import cn.keking.model.ReturnResponse; import io.mola.galimatias.GalimatiasParseException; +import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; import java.net.*; -import java.nio.charset.StandardCharsets; import java.util.UUID; +import static cn.keking.utils.KkFileUtils.isFtpUrl; +import static cn.keking.utils.KkFileUtils.isHttpUrl; + /** * @author yudian-it */ @@ -31,42 +33,26 @@ public class DownloadUtils { */ public static ReturnResponse downLoad(FileAttribute fileAttribute, String fileName) { String urlStr = fileAttribute.getUrl(); - String type = fileAttribute.getSuffix(); ReturnResponse response = new ReturnResponse<>(0, "下载成功!!!", ""); - UUID uuid = UUID.randomUUID(); - if (null == fileName) { - fileName = uuid + "." + type; - } else { // 文件后缀不一致时,以type为准(针对simText【将类txt文件转为txt】) - fileName = fileName.replace(fileName.substring(fileName.lastIndexOf(".") + 1), type); - } - String realPath = fileDir + fileName; - File dirFile = new File(fileDir); - if (!dirFile.exists() && !dirFile.mkdirs()) { - logger.error("创建目录【{}】失败,可能是权限不够,请检查", fileDir); - } + String realPath = DownloadUtils.getRelFilePath(fileName, fileAttribute); try { - URL url = new URL(urlStr); - if (url.getProtocol() != null && (url.getProtocol().toLowerCase().startsWith("file") || url.getProtocol().toLowerCase().startsWith("http"))) { - byte[] bytes = getBytesFromUrl(urlStr); - OutputStream os = new FileOutputStream(realPath); - saveBytesToOutStream(bytes, os); - } else if (url.getProtocol() != null && "ftp".equalsIgnoreCase(url.getProtocol())) { + URL url = WebUtils.normalizedURL(urlStr); + if (isHttpUrl(url)) { + File realFile = new File(realPath); + FileUtils.copyURLToFile(url, realFile); + } else if (isFtpUrl(url)) { String ftpUsername = WebUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_USERNAME); String ftpPassword = WebUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_PASSWORD); String ftpControlEncoding = WebUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_CONTROL_ENCODING); FtpUtils.download(fileAttribute.getUrl(), realPath, ftpUsername, ftpPassword, ftpControlEncoding); } else { response.setCode(1); - response.setContent(null); response.setMsg("url不能识别url" + urlStr); } response.setContent(realPath); response.setMsg(fileName); - if (FileType.simText.equals(fileAttribute.getType())) { - convertTextPlainFileCharsetToUtf8(realPath); - } return response; - } catch (IOException e) { + } catch (IOException | GalimatiasParseException e) { logger.error("文件下载失败,url:{}", urlStr, e); response.setCode(1); response.setContent(null); @@ -79,82 +65,27 @@ public class DownloadUtils { } } - public static byte[] getBytesFromUrl(String urlStr) throws IOException { - InputStream is = getInputStreamFromUrl(urlStr); - if (is == null) { - is = getInputStreamFromUrl(urlStr); - if (is == null) { - logger.error("文件下载异常:url:{}", urlStr); - throw new IOException("文件下载异常:url:" + urlStr); - } - } - return getBytesFromStream(is); - } - - public static void saveBytesToOutStream(byte[] b, OutputStream os) throws IOException { - os.write(b); - os.close(); - } - - private static InputStream getInputStreamFromUrl(String urlStr) { - try { - - URL url = io.mola.galimatias.URL.parse(urlStr).toJavaURL(); - URLConnection connection = url.openConnection(); - if (connection instanceof HttpURLConnection) { - connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); - } - return connection.getInputStream(); - } catch (IOException | GalimatiasParseException e) { - logger.warn("连接url异常:url:{}", urlStr); - return null; - } - } - - private static byte[] getBytesFromStream(InputStream is) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buffer = new byte[1024]; - int len; - while ((len = is.read(buffer)) != -1) { - baos.write(buffer, 0, len); - } - byte[] b = baos.toByteArray(); - is.close(); - baos.close(); - return b; - } /** - * 转换文本文件编码为utf8 - * 探测源文件编码,探测到编码切不为utf8则进行转码 + * 获取真实文件绝对路径 * - * @param filePath 文件路径 + * @param fileName 文件名 + * @return 文件路径 */ - private static void convertTextPlainFileCharsetToUtf8(String filePath) throws IOException { - File sourceFile = new File(filePath); - if (sourceFile.exists() && sourceFile.isFile() && sourceFile.canRead()) { - String encoding = FileUtils.getFileEncode(filePath); - if (!FileUtils.DEFAULT_FILE_ENCODING.equals(encoding)) { - // 不为utf8,进行转码 - File tmpUtf8File = new File(filePath + ".utf8"); - Writer writer = new OutputStreamWriter(new FileOutputStream(tmpUtf8File), StandardCharsets.UTF_8); - Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(sourceFile), encoding)); - char[] buf = new char[1024]; - int read; - while ((read = reader.read(buf)) > 0) { - writer.write(buf, 0, read); - } - reader.close(); - writer.close(); - // 删除源文件 - if (!sourceFile.delete()) { - logger.error("源文件【{}】删除失败,请检查文件目录权限!", filePath); - } - // 重命名 - if (tmpUtf8File.renameTo(sourceFile)) { - logger.error("临时文件【{}】重命名失败,请检查文件路径权限!", tmpUtf8File.getPath()); - } - } + private static String getRelFilePath(String fileName, FileAttribute fileAttribute) { + String type = fileAttribute.getSuffix(); + if (null == fileName) { + UUID uuid = UUID.randomUUID(); + fileName = uuid + "." + type; + } else { // 文件后缀不一致时,以type为准(针对simText【将类txt文件转为txt】) + fileName = fileName.replace(fileName.substring(fileName.lastIndexOf(".") + 1), type); } + String realPath = fileDir + fileName; + File dirFile = new File(fileDir); + if (!dirFile.exists() && !dirFile.mkdirs()) { + logger.error("创建目录【{}】失败,可能是权限不够,请检查", fileDir); + } + return realPath; } + } diff --git a/server/src/main/java/cn/keking/utils/FileUtils.java b/server/src/main/java/cn/keking/utils/KkFileUtils.java similarity index 74% rename from server/src/main/java/cn/keking/utils/FileUtils.java rename to server/src/main/java/cn/keking/utils/KkFileUtils.java index bf0d64e5..16b0db31 100644 --- a/server/src/main/java/cn/keking/utils/FileUtils.java +++ b/server/src/main/java/cn/keking/utils/KkFileUtils.java @@ -6,19 +6,39 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; +import java.net.URL; import java.util.Objects; -public class FileUtils { +public class KkFileUtils { - private static final Logger LOGGER = LoggerFactory.getLogger(FileUtils.class); + private static final Logger LOGGER = LoggerFactory.getLogger(KkFileUtils.class); public static final String DEFAULT_FILE_ENCODING = "UTF-8"; + /** + * 判断url是否是http资源 + * + * @param url url + * @return 是否http + */ + public static boolean isHttpUrl(URL url) { + return url.getProtocol().toLowerCase().startsWith("file") || url.getProtocol().toLowerCase().startsWith("http"); + } + + /** + * 判断url是否是ftp资源 + * + * @param url url + * @return 是否ftp + */ + public static boolean isFtpUrl(URL url) { + return "ftp".equalsIgnoreCase(url.getProtocol()); + } + /** * 删除单个文件 * - * @param fileName - * 要删除的文件的文件名 + * @param fileName 要删除的文件的文件名 * @return 单个文件删除成功返回true,否则返回false */ public static boolean deleteFileByName(String fileName) { @@ -39,17 +59,26 @@ public class FileUtils { } /** - * 判断文件编码格式 + * 检测文件编码格式 * * @param filePath 绝对路径 * @return 编码格式 */ public static String getFileEncode(String filePath) { - File file = new File(filePath); + return getFileEncode(new File(filePath)); + } + + /** + * 检测文件编码格式 + * + * @param file 检测的文件 + * @return 编码格式 + */ + public static String getFileEncode(File file) { CharsetPrinter cp = new CharsetPrinter(); try { String encoding = cp.guessEncoding(file); - LOGGER.info("检测到文件【{}】编码: {}", filePath, encoding); + LOGGER.info("检测到文件【{}】编码: {}", file.getAbsolutePath(), encoding); return encoding; } catch (IOException e) { LOGGER.warn("文件编码获取失败,采用默认的编码格式:UTF-8", e); @@ -59,6 +88,7 @@ public class FileUtils { /** * 通过文件名获取文件后缀 + * * @param fileName 文件名称 * @return 文件后缀 */ @@ -82,8 +112,7 @@ public class FileUtils { /** * 删除目录及目录下的文件 * - * @param dir - * 要删除的目录的文件路径 + * @param dir 要删除的目录的文件路径 * @return 目录删除成功返回true,否则返回false */ public static boolean deleteDirectory(String dir) { @@ -103,13 +132,13 @@ public class FileUtils { for (int i = 0; i < Objects.requireNonNull(files).length; i++) { // 删除子文件 if (files[i].isFile()) { - flag = FileUtils.deleteFileByName(files[i].getAbsolutePath()); + flag = KkFileUtils.deleteFileByName(files[i].getAbsolutePath()); if (!flag) { break; } - } else if (files[i].isDirectory()) { + } else if (files[i].isDirectory()) { // 删除子目录 - flag = FileUtils.deleteDirectory(files[i].getAbsolutePath()); + flag = KkFileUtils.deleteDirectory(files[i].getAbsolutePath()); if (!flag) { break; } diff --git a/server/src/main/java/cn/keking/utils/WebUtils.java b/server/src/main/java/cn/keking/utils/WebUtils.java index 7bebf61b..ec67f0b9 100644 --- a/server/src/main/java/cn/keking/utils/WebUtils.java +++ b/server/src/main/java/cn/keking/utils/WebUtils.java @@ -1,5 +1,9 @@ package cn.keking.utils; +import io.mola.galimatias.GalimatiasParseException; + +import java.net.MalformedURLException; +import java.net.URL; import java.util.HashMap; import java.util.Map; @@ -8,6 +12,16 @@ import java.util.Map; * create : 2020-12-27 1:30 上午 **/ public class WebUtils { + + /** + * 获取标准的URL + * @param urlStr url + * @return 标准的URL + */ + public static URL normalizedURL(String urlStr) throws GalimatiasParseException, MalformedURLException { + return io.mola.galimatias.URL.parse(urlStr).toJavaURL(); + } + /** * 获取url中的参数 * @@ -81,6 +95,6 @@ public class WebUtils { public static String suffixFromUrl(String url) { String nonPramStr = url.substring(0, url.contains("?") ? url.indexOf("?") : url.length()); String fileName = nonPramStr.substring(nonPramStr.lastIndexOf("/") + 1); - return FileUtils.suffixFromFileName(fileName); + return KkFileUtils.suffixFromFileName(fileName); } } 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 4bce2066..0a9d0910 100644 --- a/server/src/main/java/cn/keking/web/controller/OnlinePreviewController.java +++ b/server/src/main/java/cn/keking/web/controller/OnlinePreviewController.java @@ -6,8 +6,10 @@ import cn.keking.service.FilePreviewFactory; import cn.keking.service.cache.CacheService; import cn.keking.service.impl.OtherFilePreviewImpl; -import cn.keking.utils.DownloadUtils; import cn.keking.service.FileHandlerService; +import cn.keking.utils.WebUtils; +import io.mola.galimatias.GalimatiasParseException; +import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; @@ -21,6 +23,7 @@ import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; +import java.net.URL; import java.util.Arrays; import java.util.List; @@ -99,9 +102,10 @@ public class OnlinePreviewController { public void getCorsFile(String urlPath, HttpServletResponse response) { logger.info("下载跨域pdf文件url:{}", urlPath); try { - byte[] bytes = DownloadUtils.getBytesFromUrl(urlPath); - DownloadUtils.saveBytesToOutStream(bytes, response.getOutputStream()); - } catch (IOException e) { + URL url = WebUtils.normalizedURL(urlPath); + byte[] bytes = IOUtils.toByteArray(url); + IOUtils.write(bytes, response.getOutputStream()); + } catch (IOException | GalimatiasParseException e) { logger.error("下载跨域pdf文件异常,url:{}", urlPath, e); } }