Bladeren bron

解压方案新版测试修复乱码Linux问题

BearBen 3 jaren geleden
bovenliggende
commit
20f328906c

+ 11 - 0
server/pom.xml

@@ -28,6 +28,17 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-freemarker</artifactId>
         </dependency>
+        <!-- 对 rar5 的支持 和其他众多压缩支持 可参考 package net.sf.sevenzipjbinding.ArchiveFormat; -->
+        <dependency>
+            <groupId>net.sf.sevenzipjbinding</groupId>
+            <artifactId>sevenzipjbinding</artifactId>
+            <version>16.02-2.01</version>
+        </dependency>
+        <dependency>
+            <groupId>net.sf.sevenzipjbinding</groupId>
+            <artifactId>sevenzipjbinding-all-platforms</artifactId>
+            <version>16.02-2.01</version>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>

+ 7 - 10
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;
     }
-
 }

+ 163 - 23
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<String> imgUrls = new ArrayList<>();
         String baseUrl = BaseUrlFilter.getBaseUrl();
         try {
-            Archive archive = new Archive(new FileInputStream(filePath));
-            List<FileHeader> headers = archive.getFileHeaders();
-            headers = sortedHeaders(headers);
+            List<FileHeaderRar> items = getRar4Paths(filePath);
             String archiveFileName = fileHandlerService.getFileNameFromPath(filePath);
-            List<Map<String, FileHeader>> headersToBeExtracted = new ArrayList<>();
-            for (FileHeader header : headers) {
-                String fullName;
-                if (header.isUnicode()) {
-                    fullName = header.getFileNameW();
-                } else {
-                    fullName = header.getFileNameString();
-                }
-                // 展示名
-                String originName = getLastFileName(fullName, "\\");
+            List<Map<String, FileHeaderRar>> 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<FileHeaderRar> getRar4Paths(String paths) {
+        RandomAccessFile randomAccessFile = null;
+        IInArchive inArchive = null;
+        List<FileHeaderRar> 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<String, FileNode> appender = new HashMap<>();
@@ -206,10 +252,21 @@ public class CompressFileReader {
     private List<FileHeader> sortedHeaders(List<FileHeader> headers) {
         List<FileHeader> sortedHeaders = new ArrayList<>();
         Map<Integer, FileHeader> 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<Integer, FileHeader> 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<Map<String, FileHeader>> headersToBeExtracted;
+
+        private final List<Map<String, FileHeaderRar>> headersToBeExtract;
+
         private final Archive archive;
         /**
          * 用以删除源文件
          */
         private final String filePath;
 
-        public RarExtractorWorker(List<Map<String, FileHeader>> headersToBeExtracted, Archive archive, String filePath) {
+        public RarExtractorWorker(
+                List<Map<String, FileHeader>> headersToBeExtracted, Archive archive, String filePath) {
             this.headersToBeExtracted = headersToBeExtracted;
             this.archive = archive;
             this.filePath = filePath;
+            headersToBeExtract = null;
+        }
+
+        public RarExtractorWorker(
+                List<Map<String, FileHeaderRar>> 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) {
+        }
+
+    }
 }

+ 3 - 0
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);

+ 2 - 11
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, "压缩文件类型不受支持");
         }
     }
 }

+ 13 - 11
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);

+ 28 - 0
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;
+  }
+}