12
12
import net .sf .sevenzipjbinding .impl .RandomAccessFileInStream ;
13
13
import net .sf .sevenzipjbinding .simple .ISimpleInArchive ;
14
14
import net .sf .sevenzipjbinding .simple .ISimpleInArchiveItem ;
15
- import org .apache .commons .io .IOUtils ;
16
15
import org .springframework .stereotype .Component ;
17
- import org .springframework .util .ObjectUtils ;
18
16
19
- import java .io .*;
17
+ import java .io .BufferedOutputStream ;
18
+ import java .io .FileOutputStream ;
19
+ import java .io .IOException ;
20
+ import java .io .OutputStream ;
21
+ import java .io .RandomAccessFile ;
22
+ import java .io .UnsupportedEncodingException ;
20
23
import java .nio .charset .StandardCharsets ;
24
+ import java .nio .file .Files ;
25
+ import java .nio .file .Path ;
26
+ import java .nio .file .Paths ;
21
27
import java .util .ArrayList ;
22
28
import java .util .List ;
23
29
@@ -37,73 +43,67 @@ public CompressFileReader(FileHandlerService fileHandlerService) {
37
43
public String unRar (String filePath , String filePassword , String fileName , FileAttribute fileAttribute ) throws Exception {
38
44
List <String > imgUrls = new ArrayList <>();
39
45
String baseUrl = BaseUrlFilter .getBaseUrl ();
40
- String packagePath = "_" ; //防止文件名重复 压缩包统一生成文件添加_符号
46
+ String packagePath = "_" ;
41
47
String folderName = filePath .replace (fileDir , "" ); //修复压缩包 多重目录获取路径错误
42
- if (fileAttribute .isCompressFile ()) { //压缩包文件 直接赋予路径 不予下载
43
- folderName = "_decompression" + folderName ; //重新修改多重压缩包 生成文件路径
48
+ if (fileAttribute .isCompressFile ()) {
49
+ folderName = "_decompression" + folderName ;
44
50
}
45
- RandomAccessFile randomAccessFile = null ;
46
- IInArchive inArchive = null ;
47
- try {
48
- randomAccessFile = new RandomAccessFile (filePath , "r" );
49
- inArchive = SevenZip .openInArchive (null , new RandomAccessFileInStream (randomAccessFile ));
51
+
52
+ Path folderPath = Paths .get (fileDir , folderName + packagePath );
53
+ Files .createDirectories (folderPath );
54
+
55
+ try (RandomAccessFile randomAccessFile = new RandomAccessFile (filePath , "r" );
56
+ IInArchive inArchive = SevenZip .openInArchive (null , new RandomAccessFileInStream (randomAccessFile ))) {
57
+
50
58
ISimpleInArchive simpleInArchive = inArchive .getSimpleInterface ();
51
- final String [] str = {null };
52
59
for (final ISimpleInArchiveItem item : simpleInArchive .getArchiveItems ()) {
53
60
if (!item .isFolder ()) {
54
- ExtractOperationResult result ;
55
- String finalFolderName = folderName ;
56
- result = item .extractSlow (data -> {
57
- try {
58
- str [0 ] = RarUtils .getUtf8String (item .getPath ());
59
- if (RarUtils .isMessyCode (str [0 ])) {
60
- str [0 ] = new String (item .getPath ().getBytes (StandardCharsets .ISO_8859_1 ), "gbk" );
61
- }
62
- str [0 ] = str [0 ].replace ("\\ " , File .separator ); //Linux 下路径错误
63
- String str1 = str [0 ].substring (0 , str [0 ].lastIndexOf (File .separator ) + 1 );
64
- File file = new File (fileDir , finalFolderName + packagePath + File .separator + str1 );
65
- if (!file .exists ()) {
66
- file .mkdirs ();
67
- }
68
- OutputStream out = new FileOutputStream (fileDir + finalFolderName + packagePath + File .separator + str [0 ], true );
69
- IOUtils .write (data , out );
70
- out .close ();
71
- } catch (Exception e ) {
72
- e .printStackTrace ();
73
- return Integer .parseInt (null );
61
+ final Path filePathInsideArchive = getFilePathInsideArchive (item , folderPath );
62
+ ExtractOperationResult result = item .extractSlow (data -> {
63
+ try (OutputStream out = new BufferedOutputStream (new FileOutputStream (filePathInsideArchive .toFile (), true ))) {
64
+ out .write (data );
65
+ } catch (IOException e ) {
66
+ throw new RuntimeException (e );
74
67
}
75
68
return data .length ;
76
69
}, filePassword );
77
- if ( result == ExtractOperationResult . OK ) {
78
- FileType type = FileType . typeFromUrl ( str [ 0 ]);
79
- if ( type . equals ( FileType . PICTURE )) {
80
- imgUrls . add ( baseUrl + folderName + packagePath + "/" + str [ 0 ]. replace ( " \\ " , "/" ));
81
- }
82
- fileHandlerService . putImgCache ( fileName + packagePath , imgUrls );
83
- } else {
84
- return null ;
70
+
71
+ if ( result != ExtractOperationResult . OK ) {
72
+ throw new Exception ( "Failed to extract RAR file." );
73
+ }
74
+
75
+ FileType type = FileType . typeFromUrl ( filePathInsideArchive . toString () );
76
+ if ( type . equals ( FileType . PICTURE )) {
77
+ imgUrls . add ( baseUrl + folderPath . relativize ( filePathInsideArchive ). toString (). replace ( " \\ " , "/" )) ;
85
78
}
86
79
}
87
80
}
88
- return folderName + packagePath ;
81
+ fileHandlerService . putImgCache ( fileName + packagePath , imgUrls ) ;
89
82
} catch (Exception e ) {
90
- throw new Exception (e );
91
- } finally {
92
- if (inArchive != null ) {
93
- try {
94
- inArchive .close ();
95
- } catch (SevenZipException e ) {
96
- System .err .println ("Error closing archive: " + e );
97
- }
98
- }
99
- if (randomAccessFile != null ) {
100
- try {
101
- randomAccessFile .close ();
102
- } catch (IOException e ) {
103
- System .err .println ("Error closing file: " + e );
104
- }
105
- }
83
+ throw new Exception ("Error processing RAR file: " + e .getMessage (), e );
84
+ }
85
+ return folderName + packagePath ;
86
+ }
87
+
88
+ private Path getFilePathInsideArchive (ISimpleInArchiveItem item , Path folderPath ) throws SevenZipException , UnsupportedEncodingException {
89
+ String insideFileName = RarUtils .getUtf8String (item .getPath ());
90
+ if (RarUtils .isMessyCode (insideFileName )) {
91
+ insideFileName = new String (item .getPath ().getBytes (StandardCharsets .ISO_8859_1 ), "gbk" );
92
+ }
93
+
94
+ // 正规化路径并验证是否安全
95
+ Path normalizedPath = folderPath .resolve (insideFileName ).normalize ();
96
+ if (!normalizedPath .startsWith (folderPath )) {
97
+ throw new SecurityException ("Unsafe path detected: " + insideFileName );
106
98
}
99
+
100
+ try {
101
+ Files .createDirectories (normalizedPath .getParent ());
102
+ } catch (IOException e ) {
103
+ throw new RuntimeException ("Failed to create directory: " + normalizedPath .getParent (), e );
104
+ }
105
+ return normalizedPath ;
107
106
}
108
107
108
+
109
109
}
0 commit comments