-
Notifications
You must be signed in to change notification settings - Fork 5
/
unarchive_file.go
243 lines (224 loc) · 5.3 KB
/
unarchive_file.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
package rod_helper
import (
"archive/zip"
"bytes"
"compress/flate"
"github.com/bodgit/sevenzip"
"github.com/mholt/archiver/v3"
"github.com/pkg/errors"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
"io"
"io/fs"
"os"
"path/filepath"
"strings"
)
// UnArchiveFileEx 发现打包的字幕内部还有一层压缩包···所以···
func UnArchiveFileEx(fileFullPath, desRootPath string) error {
// 先进行一次解压
err := UnArchiveFile(fileFullPath, desRootPath)
if err != nil {
return err
}
// --------------------------------------------------
doUnzipFun := func() error {
// 判断一次
needUnzipFileFPaths := make([]string, 0)
err = filepath.Walk(desRootPath, func(path string, info fs.FileInfo, err error) error {
if info.IsDir() == true {
return nil
}
nowExt := filepath.Ext(path)
// 然后对于解压的内容再次进行判断
if nowExt != ".zip" && nowExt != ".tar" && nowExt != ".rar" && nowExt != ".7z" {
return nil
} else {
needUnzipFileFPaths = append(needUnzipFileFPaths, path)
}
return nil
})
if err != nil {
return err
}
// 如果有压缩包,那么就继续解压,然后删除压缩包
for _, needUnzipFileFPath := range needUnzipFileFPaths {
err = UnArchiveFile(needUnzipFileFPath, desRootPath)
if err != nil {
return err
}
err = os.Remove(needUnzipFileFPath)
if err != nil {
return err
}
}
return nil
}
// 第二次解压
err = doUnzipFun()
if err != nil {
return err
}
// 第三次解压
err = doUnzipFun()
if err != nil {
return err
}
// 第四次解压
err = doUnzipFun()
if err != nil {
return err
}
return nil
}
// UnArchiveFile 7z 以外的都能搞定中文编码的问题,但是 7z 有梗,需要单独的库去解析,且编码是解决不了的,以后他们搞定了再测试
// 所以效果就是,7z 外的压缩包文件解压ok,字幕可以正常从名称解析出是简体还是繁体,但是7z就没办法了,一定乱码
func UnArchiveFile(fileFullPath, desRootPath string) error {
switch filepath.Ext(strings.ToLower(fileFullPath)) {
case ".zip":
z := archiver.Zip{
CompressionLevel: flate.DefaultCompression,
MkdirAll: true,
SelectiveCompression: true,
ContinueOnError: false,
OverwriteExisting: true,
ImplicitTopLevelFolder: false,
}
err := z.Walk(fileFullPath, func(f archiver.File) error {
if f.IsDir() == true {
return nil
}
zfh, ok := f.Header.(zip.FileHeader)
if ok {
err := processOneFile(f, zfh.NonUTF8, desRootPath)
if err != nil {
return err
}
}
return nil
})
if err != nil {
return err
}
case ".tar":
z := archiver.Tar{
MkdirAll: true,
ContinueOnError: false,
OverwriteExisting: true,
ImplicitTopLevelFolder: false,
StripComponents: 1,
}
err := z.Walk(fileFullPath, func(f archiver.File) error {
if f.IsDir() == true {
return nil
}
err := processOneFile(f, false, desRootPath)
if err != nil {
return err
}
return nil
})
if err != nil {
return err
}
case ".rar":
z := archiver.Rar{
MkdirAll: true,
ContinueOnError: false,
OverwriteExisting: true,
ImplicitTopLevelFolder: false,
StripComponents: 1,
}
err := z.Walk(fileFullPath, func(f archiver.File) error {
if f.IsDir() == true {
return nil
}
err := processOneFile(f, false, desRootPath)
if err != nil {
return err
}
return nil
})
if err != nil {
return err
}
case ".7z":
return unArr7z(fileFullPath, desRootPath)
default:
return errors.New("not support un archive file ext")
}
return nil
}
func processOneFile(f archiver.File, notUTF8 bool, desRootPath string) error {
decodeName := f.Name()
if notUTF8 == true {
//ouBytes, err := ChangeFileCoding2UTF8([]byte(f.Name()))
//if err != nil {
// return err
//}
i := bytes.NewReader([]byte(f.Name()))
decoder := transform.NewReader(i, simplifiedchinese.GB18030.NewDecoder())
content, _ := io.ReadAll(decoder)
decodeName = string(content)
//decodeName = string(ouBytes)
}
var chunk []byte
buf := make([]byte, 1024)
for {
n, err := f.Read(buf)
if err != nil && err != io.EOF {
return err
}
//说明读取结束
if n == 0 {
break
}
//读取到最终的缓冲区中
chunk = append(chunk, buf[:n]...)
}
err := WriteFile(filepath.Join(desRootPath, decodeName), chunk)
if err != nil {
return err
}
return nil
}
func unArr7z(fileFullPath, desRootPath string) error {
r, err := sevenzip.OpenReader(fileFullPath)
if err != nil {
return err
}
defer r.Close()
for _, file := range r.File {
err = un7zOneFile(file, desRootPath)
if err != nil {
return err
}
}
return nil
}
func un7zOneFile(file *sevenzip.File, desRootPath string) error {
rc, err := file.Open()
if err != nil {
return err
}
defer rc.Close()
data, err := io.ReadAll(rc)
if err != nil {
return err
}
decodeName := file.Name
decodeName = filepath.Base(decodeName)
err = WriteFile(filepath.Join(desRootPath, decodeName), data)
if err != nil {
return err
}
return nil
}
func IsWantedArchiveExtName(fileName string) bool {
switch strings.ToLower(filepath.Ext(fileName)) {
case ".zip", ".tar", ".rar", "7z":
return true
default:
return false
}
}