123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- package archive_helper
- import (
- "archive/zip"
- "bytes"
- "compress/flate"
- "errors"
- "io"
- "io/fs"
- "os"
- "path/filepath"
- "strings"
- "unicode/utf8"
- "github.com/ChineseSubFinder/ChineseSubFinder/pkg"
- "github.com/bodgit/sevenzip"
- "github.com/mholt/archiver/v3"
- "golang.org/x/text/encoding/simplifiedchinese"
- "golang.org/x/text/transform"
- )
- // 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
- }
- } else {
- // 需要检测文件名是否是乱码
- err := processOneFile(f, !utf8.ValidString(f.Name()), 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 := pkg.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 = pkg.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
- }
- }
|