diff --git a/server/pom.xml b/server/pom.xml index 72a1941a..485f0424 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -28,6 +28,17 @@ org.springframework.boot spring-boot-starter-freemarker + + + net.sf.sevenzipjbinding + sevenzipjbinding + 16.02-2.01 + + + net.sf.sevenzipjbinding + sevenzipjbinding-all-platforms + 16.02-2.01 + org.springframework.boot spring-boot-starter-web diff --git a/server/src/main/java/cn/keking/model/FileAttribute.java b/server/src/main/java/cn/keking/model/FileAttribute.java index 036bef9a..6ba903b7 100644 --- a/server/src/main/java/cn/keking/model/FileAttribute.java +++ b/server/src/main/java/cn/keking/model/FileAttribute.java @@ -15,6 +15,7 @@ public class FileAttribute { private String fileKey; private String officePreviewType = ConfigConstants.getOfficePreviewType(); private String tifPreviewType; + private Boolean skipDownLoad = false; public FileAttribute() { } @@ -34,15 +35,6 @@ public class FileAttribute { this.officePreviewType = officePreviewType; } - public FileAttribute(FileType type, String suffix, String name, String url, String officePreviewType, String tifPreviewType) { - this.type = type; - this.suffix = suffix; - this.name = name; - this.url = url; - this.officePreviewType = officePreviewType; - this.tifPreviewType = tifPreviewType; - } - public String getFileKey() { return fileKey; } @@ -90,7 +82,13 @@ public class FileAttribute { public void setUrl(String url) { this.url = url; } + public Boolean getSkipDownLoad() { + return skipDownLoad; + } + public void setSkipDownLoad(Boolean skipDownLoad) { + this.skipDownLoad = skipDownLoad; + } public String getTifPreviewType() { return tifPreviewType; } @@ -98,5 +96,4 @@ public class FileAttribute { public void setTifPreviewType(String previewType) { this.tifPreviewType = previewType; } - } diff --git a/server/src/main/java/cn/keking/service/CompressFileReader.java b/server/src/main/java/cn/keking/service/CompressFileReader.java index c11e5909..e73751a5 100644 --- a/server/src/main/java/cn/keking/service/CompressFileReader.java +++ b/server/src/main/java/cn/keking/service/CompressFileReader.java @@ -2,6 +2,7 @@ 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; @@ -9,10 +10,14 @@ 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.impl.RandomAccessFileInStream; +import net.sf.sevenzipjbinding.simple.ISimpleInArchive; import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry; import org.apache.commons.compress.archivers.sevenz.SevenZFile; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipFile; +import org.apache.commons.io.FileUtils; import org.springframework.stereotype.Component; import java.io.*; @@ -24,6 +29,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; /** * @author yudian-it @@ -99,44 +105,84 @@ public class CompressFileReader { List imgUrls = new ArrayList<>(); String baseUrl = BaseUrlFilter.getBaseUrl(); try { - Archive archive = new Archive(new FileInputStream(filePath)); - List headers = archive.getFileHeaders(); - headers = sortedHeaders(headers); + List items = getRar4Paths(filePath); String archiveFileName = fileHandlerService.getFileNameFromPath(filePath); - List> headersToBeExtracted = new ArrayList<>(); - for (FileHeader header : headers) { - String fullName; - if (header.isUnicode()) { - fullName = header.getFileNameW(); - } else { - fullName = header.getFileNameString(); - } - // 展示名 - String originName = getLastFileName(fullName, "\\"); + List> headersToBeExtract = new ArrayList<>(); + for (FileHeaderRar header : items) { + String fullName = header.getFileNameW(); + String originName = getLastFileName(fullName, File.separator); String childName = originName; - boolean directory = header.isDirectory(); + boolean directory = header.getDirectory(); if (!directory) { childName = archiveFileName + "_" + originName; - headersToBeExtracted.add(Collections.singletonMap(childName, header)); + headersToBeExtract.add(Collections.singletonMap(childName, header)); } - String parentName = getLast2FileName(fullName, "\\", archiveFileName); + String parentName = getLast2FileName(fullName, File.separator, archiveFileName); FileType type = FileType.typeFromUrl(childName); - if (type.equals(FileType.PICTURE)) {//添加图片文件到图片列表 + if (type.equals(FileType.PICTURE)) { imgUrls.add(baseUrl + childName); } - FileNode node = new FileNode(originName, childName, parentName, new ArrayList<>(), directory, fileKey); + FileNode node = + new FileNode(originName, childName, parentName, new ArrayList<>(), directory, fileKey); addNodes(appender, parentName, node); appender.put(childName, node); } - executors.submit(new RarExtractorWorker(headersToBeExtracted, archive, filePath)); fileHandlerService.putImgCache(fileKey, imgUrls); + executors.submit(new RarExtractorWorker(headersToBeExtract, filePath)); return new ObjectMapper().writeValueAsString(appender.get("")); - } catch (RarException | IOException e) { + } catch (IOException e) { e.printStackTrace(); } return null; } + public List getRar4Paths(String 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 { + return new FileHeaderRar(o.getPath(), o.isFolder()); + } catch (SevenZipException e) { + e.printStackTrace(); + } + return null; + }) + .collect(Collectors.toList()) + .stream() + .sorted(Comparator.comparing(FileHeaderRar::getFileNameW)) + .collect(Collectors.toList()); + } catch (Exception e) { + System.err.println("Error occurs: " + e); + } finally { + if (inArchive != null) { + try { + inArchive.close(); + } catch (SevenZipException e) { + System.err.println("Error closing archive: " + e); + } + } + if (randomAccessFile != null) { + try { + randomAccessFile.close(); + } catch (IOException e) { + System.err.println("Error closing file: " + e); + } + } + } + return itemPath; + } + public String read7zFile(String filePath, String fileKey) { String archiveSeparator = "/"; Map appender = new HashMap<>(); @@ -206,10 +252,21 @@ public class CompressFileReader { private List sortedHeaders(List headers) { List sortedHeaders = new ArrayList<>(); Map mapHeaders = new TreeMap<>(); - headers.forEach(header -> mapHeaders.put(new Integer(0).equals(header.getFileNameW().length()) ? header.getFileNameString().length() : header.getFileNameW().length(), header)); + headers.forEach( + header -> + mapHeaders.put( + new Integer(0).equals(header.getFileNameW().length()) + ? header.getFileNameString().length() + : header.getFileNameW().length(), + header)); for (Map.Entry entry : mapHeaders.entrySet()) { for (FileHeader header : headers) { - if (entry.getKey().equals(new Integer(0).equals(header.getFileNameW().length()) ? header.getFileNameString().length() : header.getFileNameW().length())) { + if (entry + .getKey() + .equals( + new Integer(0).equals(header.getFileNameW().length()) + ? header.getFileNameString().length() + : header.getFileNameW().length())) { sortedHeaders.add(header); } } @@ -445,16 +502,29 @@ public class CompressFileReader { 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) { + 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 @@ -480,4 +550,74 @@ public class CompressFileReader { } } } + + 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) { + } + + } } diff --git a/server/src/main/java/cn/keking/service/FileHandlerService.java b/server/src/main/java/cn/keking/service/FileHandlerService.java index 67ec1fc7..0a7a6c0a 100644 --- a/server/src/main/java/cn/keking/service/FileHandlerService.java +++ b/server/src/main/java/cn/keking/service/FileHandlerService.java @@ -270,6 +270,9 @@ public class FileHandlerService { type = FileType.typeFromUrl(url); suffix = WebUtils.suffixFromUrl(url); } + if (url.contains("?fileKey=")) { + attribute.setSkipDownLoad(true); + } attribute.setType(type); attribute.setName(fileName); attribute.setSuffix(suffix); diff --git a/server/src/main/java/cn/keking/service/impl/CompressFilePreviewImpl.java b/server/src/main/java/cn/keking/service/impl/CompressFilePreviewImpl.java index ed2d2ae9..bd71b844 100644 --- a/server/src/main/java/cn/keking/service/impl/CompressFilePreviewImpl.java +++ b/server/src/main/java/cn/keking/service/impl/CompressFilePreviewImpl.java @@ -40,16 +40,7 @@ public class CompressFilePreviewImpl implements FilePreview { return otherFilePreview.notSupportedFile(model, fileAttribute, response.getMsg()); } String filePath = response.getContent(); - if ("zip".equalsIgnoreCase(suffix) || "jar".equalsIgnoreCase(suffix) || "gzip".equalsIgnoreCase(suffix)) { - fileTree = compressFileReader.readZipFile(filePath, fileName); - } else if ("rar".equalsIgnoreCase(suffix)) { - fileTree = compressFileReader.unRar(filePath, fileName); - } else if ("7z".equalsIgnoreCase(suffix)) { - fileTree = compressFileReader.read7zFile(filePath, fileName); - } - if (fileTree != null && !"null".equals(fileTree) && ConfigConstants.isCacheEnabled()) { - fileHandlerService.addConvertedFile(fileName, fileTree); - } + fileTree = compressFileReader.unRar(filePath, fileName); } else { fileTree = fileHandlerService.getConvertedFile(fileName); } @@ -57,7 +48,7 @@ public class CompressFilePreviewImpl implements FilePreview { model.addAttribute("fileTree", fileTree); return COMPRESS_FILE_PREVIEW_PAGE; } else { - return otherFilePreview.notSupportedFile(model, fileAttribute, "压缩文件类型不受支持,尝试在压缩的时候选择RAR4格式"); + return otherFilePreview.notSupportedFile(model, fileAttribute, "压缩文件类型不受支持"); } } } diff --git a/server/src/main/java/cn/keking/utils/DownloadUtils.java b/server/src/main/java/cn/keking/utils/DownloadUtils.java index 9e8c3d97..5966eaa7 100644 --- a/server/src/main/java/cn/keking/utils/DownloadUtils.java +++ b/server/src/main/java/cn/keking/utils/DownloadUtils.java @@ -37,17 +37,19 @@ public class DownloadUtils { String realPath = DownloadUtils.getRelFilePath(fileName, fileAttribute); try { 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.setMsg("url不能识别url" + urlStr); + if (!fileAttribute.getSkipDownLoad()) { + 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.setMsg("url不能识别url" + urlStr); + } } response.setContent(realPath); response.setMsg(fileName); diff --git a/server/src/main/java/cn/keking/utils/FileHeaderRar.java b/server/src/main/java/cn/keking/utils/FileHeaderRar.java new file mode 100644 index 00000000..4742f974 --- /dev/null +++ b/server/src/main/java/cn/keking/utils/FileHeaderRar.java @@ -0,0 +1,28 @@ +package cn.keking.utils; + +public class FileHeaderRar { + + private String fileNameW; + private Boolean isDirectory; + + public FileHeaderRar(String fileNameW, Boolean isDirectory) { + this.fileNameW = fileNameW; + this.isDirectory = isDirectory; + } + + public String getFileNameW() { + return fileNameW; + } + + public void setFileNameW(String fileNameW) { + this.fileNameW = fileNameW; + } + + public Boolean getDirectory() { + return isDirectory; + } + + public void setDirectory(Boolean directory) { + isDirectory = directory; + } +}