diff --git a/server/src/main/java/cn/keking/service/CompressFileReader.java b/server/src/main/java/cn/keking/service/CompressFileReader.java index 7e13fe76..f8578ead 100644 --- a/server/src/main/java/cn/keking/service/CompressFileReader.java +++ b/server/src/main/java/cn/keking/service/CompressFileReader.java @@ -1,32 +1,24 @@ package cn.keking.service; - import cn.keking.config.ConfigConstants; import cn.keking.model.FileType; -import cn.keking.utils.FileHeaderRar; -import cn.keking.utils.KkFileUtils; import cn.keking.web.filter.BaseUrlFilter; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.github.junrar.Archive; -import com.github.junrar.exception.RarException; -import com.github.junrar.rarfile.FileHeader; -import net.sf.sevenzipjbinding.*; +import net.sf.sevenzipjbinding.ExtractOperationResult; +import net.sf.sevenzipjbinding.IInArchive; +import net.sf.sevenzipjbinding.SevenZip; +import net.sf.sevenzipjbinding.SevenZipException; import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream; import net.sf.sevenzipjbinding.simple.ISimpleInArchive; +import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem; +import org.apache.commons.io.IOUtils; import org.springframework.stereotype.Component; import java.io.*; -import java.math.BigDecimal; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.text.CollationKey; -import java.text.Collator; -import java.util.*; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +import java.util.ArrayList; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Collectors; /** * @author yudian-it @@ -34,16 +26,11 @@ import java.util.stream.Collectors; */ @Component public class CompressFileReader { - - private static final Pattern pattern = Pattern.compile("^\\d+"); private final FileHandlerService fileHandlerService; - private final String fileDir = ConfigConstants.getFileDir(); - private final ExecutorService executors = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); - public CompressFileReader(FileHandlerService fileHandlerService) { this.fileHandlerService = fileHandlerService; } - + private static final String fileDir = ConfigConstants.getFileDir(); public static byte[] getUTF8BytesFromGBKString(String gbkStr) { int n = gbkStr.length(); byte[] utfBytes = new byte[3 * n]; @@ -92,21 +79,15 @@ public class CompressFileReader { */ private static boolean isChinese(char c) { Character.UnicodeBlock ub = Character.UnicodeBlock.of(c); - if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS + return ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION - || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) { - return true; - } - return false; + || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS; } public static boolean judge(char c){ - if((c >='0' && c<='9')||(c >='a' && c<='z' || c >='A' && c<='Z')){ - return true; - } - return false; + return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'); } public static boolean isMessyCode(String strName) { //去除字符串中的空格 制表符 换行 回车 @@ -117,8 +98,7 @@ public class CompressFileReader { String temp = after.replaceAll("\\p{P}", ""); //处理之后转换成字符数组 char[] ch = temp.trim().toCharArray(); - for (int i = 0; i < ch.length; i++) { - char c = ch[i]; + for (char c : ch) { //判断是否是数字或者英文字符 if (!judge(c)) { //判断是否是中日韩文 @@ -131,74 +111,61 @@ public class CompressFileReader { //表示不是乱码 返回false return false; } - - public String unRar(String filePath, String fileKey) { - Map appender = new HashMap<>(); + public String unRar(String paths, String passWord, String fileName) { List imgUrls = new ArrayList<>(); String baseUrl = BaseUrlFilter.getBaseUrl(); - try { - List items = getRar4Paths(filePath); - String archiveFileName = fileHandlerService.getFileNameFromPath(filePath); - List> headersToBeExtract = new ArrayList<>(); - for (FileHeaderRar header : items) { - String fullName = header.getFileNameW(); - String originName = getLastFileName(fullName); - String childName = originName; - boolean directory = header.getDirectory(); - if (!directory) { - childName = archiveFileName + "_" + originName; - headersToBeExtract.add(Collections.singletonMap(childName, header)); - } - String parentName = getLast2FileName(fullName, archiveFileName); - FileType type = FileType.typeFromUrl(childName); - if (type.equals(FileType.PICTURE)) { - imgUrls.add(baseUrl + childName); - } - FileNode node = - new FileNode(originName, childName, parentName, new ArrayList<>(), directory, fileKey); - addNodes(appender, parentName, node); - appender.put(childName, node); - } - fileHandlerService.putImgCache(fileKey, imgUrls); - executors.submit(new RarExtractorWorker(headersToBeExtract, filePath)); - return new ObjectMapper().writeValueAsString(appender.get("")); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - public List getRar4Paths(String paths) { + String archiveFileName = fileHandlerService.getFileNameFromPath(paths); RandomAccessFile randomAccessFile = null; IInArchive inArchive = null; - List itemPath = null; try { randomAccessFile = new RandomAccessFile(paths, "r"); inArchive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile)); String folderName = paths.substring(paths.lastIndexOf(File.separator) + 1); String extractPath = paths.substring(0, paths.lastIndexOf(folderName)); - inArchive.extract(null, false, new ExtractCallback(inArchive, extractPath, folderName + "_")); - ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface(); - itemPath = Arrays.stream(simpleInArchive.getArchiveItems()).map(o -> { - try { - String path = getUtf8String(o.getPath()); - if (isMessyCode(path)){ - path = new String(o.getPath().getBytes(StandardCharsets.ISO_8859_1), "GBK"); - } - return new FileHeaderRar(path, o.isFolder()); - } catch (SevenZipException e) { - e.printStackTrace(); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - return null; - }) - .collect(Collectors.toList()) - .stream() - .sorted(Comparator.comparing(FileHeaderRar::getFileNameW)) - .collect(Collectors.toList()); + ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface(); + final String[] str = {null}; + for (final ISimpleInArchiveItem item : simpleInArchive.getArchiveItems()) { + if (!item.isFolder()) { + ExtractOperationResult result; + result = item.extractSlow(data -> { + try { + str[0] = getUtf8String(item.getPath()); + if (isMessyCode(str[0])){ + str[0] = new String(item.getPath().getBytes(StandardCharsets.ISO_8859_1), "gbk"); + } + str[0] = str[0].replace("\\", File.separator); //Linux 下路径错误 + String str1 = str[0].substring(0, str[0].lastIndexOf(File.separator)+ 1); + File file = new File(extractPath, folderName + "_" + File.separator + str1); + if (!file.exists()) { + file.mkdirs(); + } + OutputStream out = new FileOutputStream( extractPath+ folderName + "_" + File.separator + str[0], true); + IOUtils.write(data, out); + out.close(); + } catch (Exception e) { + e.printStackTrace(); + } + return data.length; + }, passWord); + if (result == ExtractOperationResult.OK) { + FileType type = FileType.typeFromUrl(str[0]); + if (type.equals(FileType.PICTURE)) { + // System.out.println( baseUrl +folderName + "_" + str[0]); + imgUrls.add(baseUrl +folderName + "_/" + str[0].replace("\\", "/")); + } + fileHandlerService.putImgCache(fileName, imgUrls); + } else { + return "error"; + } + } + } + return archiveFileName + "_"; } catch (Exception e) { - System.err.println("Error occurs: " + e); + String Str1 = String.valueOf(e); + if (Str1.contains("Password")) { + return "Password"; + } + return null; } finally { if (inArchive != null) { try { @@ -215,276 +182,34 @@ public class CompressFileReader { } } } - return itemPath; } - - private void addNodes(Map appender, String parentName, FileNode node) { - if (appender.containsKey(parentName)) { - appender.get(parentName).getChildList().add(node); - appender.get(parentName).getChildList().sort(sortComparator); - } else { - // 根节点 - FileNode nodeRoot = new FileNode(parentName, parentName, "", new ArrayList<>(), true); - nodeRoot.getChildList().add(node); - appender.put("", nodeRoot); - appender.put(parentName, nodeRoot); - } + /** + * 读取文件目录树 + */ + public static List getTree(String rootPath) { + List nodes = new ArrayList<>(); + File file = new File(fileDir+rootPath); + ZtreeNodeVo node = traverse(file); + nodes.add(node); + return nodes; } - - private static String getLast2FileName(String fullName, String rootName) { - if (fullName.endsWith(File.separator)) { - fullName = fullName.substring(0, fullName.length() - 1); - } - // 1.获取剩余部分 - int endIndex = fullName.lastIndexOf(File.separator); - String leftPath = fullName.substring(0, endIndex == -1 ? 0 : endIndex); - if (leftPath.length() > 1) { - // 2.获取倒数第二个 - return getLastFileName(leftPath); - } else { - return rootName; - } - } - - private static String getLastFileName(String fullName) { - if (fullName.endsWith(File.separator)) { - fullName = fullName.substring(0, fullName.length() - 1); - } - String newName = fullName; - if (fullName.contains(File.separator)) { - newName = fullName.substring(fullName.lastIndexOf(File.separator) + 1); - } - return newName; - } - - public static Comparator sortComparator = new Comparator() { - final Collator cmp = Collator.getInstance(Locale.US); - - @Override - public int compare(FileNode o1, FileNode o2) { - // 判断两个对比对象是否是开头包含数字,如果包含数字则获取数字并按数字真正大小进行排序 - BigDecimal num1, num2; - if (null != (num1 = isStartNumber(o1)) - && null != (num2 = isStartNumber(o2))) { - return num1.subtract(num2).intValue(); + private static ZtreeNodeVo traverse(File file) { + ZtreeNodeVo pathNodeVo = new ZtreeNodeVo(); + pathNodeVo.setId(file.getAbsolutePath().replace(fileDir, "").replace("\\", "/")); + pathNodeVo.setName(file.getName()); + pathNodeVo.setPid(file.getParent().replace(fileDir, "").replace("\\", "/")); + if (file.isDirectory()) { + List subNodeVos = new ArrayList<>(); + File[] subFiles = file.listFiles(); + if (subFiles == null) { + return pathNodeVo; } - CollationKey c1 = cmp.getCollationKey(o1.getOriginName()); - CollationKey c2 = cmp.getCollationKey(o2.getOriginName()); - return cmp.compare(c1.getSourceString(), c2.getSourceString()); - } - }; - - private static BigDecimal isStartNumber(FileNode src) { - Matcher matcher = pattern.matcher(src.getOriginName()); - if (matcher.find()) { - return new BigDecimal(matcher.group()); - } - return null; - } - - public static class FileNode { - - private String originName; - private String fileName; - private String parentFileName; - private boolean directory; - //用于图片预览时寻址 - private String fileKey; - private List childList; - - public FileNode(String originName, String fileName, String parentFileName, List childList, boolean directory) { - this.originName = originName; - this.fileName = fileName; - this.parentFileName = parentFileName; - this.childList = childList; - this.directory = directory; - } - - public FileNode(String originName, String fileName, String parentFileName, List childList, boolean directory, String fileKey) { - this.originName = originName; - this.fileName = fileName; - this.parentFileName = parentFileName; - this.childList = childList; - this.directory = directory; - this.fileKey = fileKey; - } - - public String getFileKey() { - return fileKey; - } - - public void setFileKey(String fileKey) { - this.fileKey = fileKey; - } - - public String getFileName() { - return fileName; - } - - public void setFileName(String fileName) { - this.fileName = fileName; - } - - public String getParentFileName() { - return parentFileName; - } - - public void setParentFileName(String parentFileName) { - this.parentFileName = parentFileName; - } - - public List getChildList() { - return childList; - } - - public void setChildList(List childList) { - this.childList = childList; - } - - @Override - public String toString() { - try { - return new ObjectMapper().writeValueAsString(this); - } catch (JsonProcessingException e) { - e.printStackTrace(); - return ""; + for (File subFile : subFiles) { + ZtreeNodeVo subNodeVo = traverse(subFile); + subNodeVos.add(subNodeVo); } + pathNodeVo.setChildren(subNodeVos); } - - public String getOriginName() { - return originName; - } - - public void setOriginName(String originName) { - this.originName = originName; - } - - public boolean isDirectory() { - return directory; - } - - public void setDirectory(boolean directory) { - this.directory = directory; - } - } - - class RarExtractorWorker implements Runnable { - private final List> headersToBeExtracted; - - private final List> headersToBeExtract; - - private final Archive archive; - /** - * 用以删除源文件 - */ - private final String filePath; - - public RarExtractorWorker( - List> headersToBeExtracted, Archive archive, String filePath) { - this.headersToBeExtracted = headersToBeExtracted; - this.archive = archive; - this.filePath = filePath; - headersToBeExtract = null; - } - - public RarExtractorWorker( - List> headersToBeExtract, String filePath) { - this.headersToBeExtract = headersToBeExtract; - this.filePath = filePath; - archive = null; - headersToBeExtracted = null; - } - - @Override - public void run() { - for (Map entryMap : headersToBeExtracted) { - String childName = entryMap.keySet().iterator().next(); - extractRarFile(childName, entryMap.values().iterator().next(), archive); - } - try { - archive.close(); - } catch (IOException e) { - e.printStackTrace(); - } - KkFileUtils.deleteFileByPath(filePath); - } - - private void extractRarFile(String childName, FileHeader header, Archive archive) { - String outPath = fileDir + childName; - try (OutputStream ot = new FileOutputStream(outPath)) { - archive.extractFile(header, ot); - } catch (IOException | RarException e) { - e.printStackTrace(); - } - } - } - - private static class ExtractCallback implements IArchiveExtractCallback { - private final IInArchive inArchive; - - private final String extractPath; - private final String folderName; - - public ExtractCallback(IInArchive inArchive, String extractPath, String folderName) { - this.inArchive = inArchive; - if (!extractPath.endsWith("/") && !extractPath.endsWith("\\")) { - extractPath += File.separator; - } - this.extractPath = extractPath; - this.folderName = folderName; - } - - @Override - public void setTotal(long total) { - - } - - @Override - public void setCompleted(long complete) { - - } - - @Override - public ISequentialOutStream getStream(int index, ExtractAskMode extractAskMode) throws SevenZipException { - String filePath = inArchive.getStringProperty(index, PropID.PATH); - String real = folderName + filePath.substring(filePath.lastIndexOf(File.separator) + 1); - File f = new File(extractPath + real); - f.delete(); - return data -> { - FileOutputStream fos = null; - try { - File path = new File(extractPath + real); - if (!path.getParentFile().exists()) { - path.getParentFile().mkdirs(); - } - if (!path.exists()) { - path.createNewFile(); - } - fos = new FileOutputStream(path, true); - fos.write(data); - } catch (IOException e) { - e.printStackTrace(); - } finally { - try { - if (fos != null) { - fos.flush(); - fos.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - return data.length; - }; - } - - @Override - public void prepareOperation(ExtractAskMode extractAskMode) { - - } - - @Override - public void setOperationResult(ExtractOperationResult extractOperationResult) { - } + return pathNodeVo; } }