package main import ( "archive/zip" "bytes" "fmt" "io" "io/ioutil" "log" "os" "path/filepath" "strings" "github.com/axgle/mahonia" "github.com/nwaples/rardecode" "github.com/studio-b12/gowebdav" "golang.org/x/text/encoding/simplifiedchinese" "golang.org/x/text/transform" ) /* 1.上云盘获取到zip、下载到本地 2.解压 3.上传云盘 4.删除本地文件 */ func do(archivePath, extractPath string) { // archivePath = "path/to/your/archive.zip" // 压缩包路径 // extractPath = "path/to/your/extracted" // 解压路径 err := extractAndFlatten(archivePath, extractPath) if err != nil { fmt.Printf("解压缩出错:%v\n", err) return } log.Println("压缩包路径:", archivePath) log.Println("解压路径:", extractPath) fmt.Println("解压缩完成!") } func extractAndFlatten(archivePath, extractPath string) error { // 获取压缩包后缀名 ext := strings.ToLower(filepath.Ext(archivePath)) switch ext { case ".zip": return extractAndFlattenZip(archivePath, extractPath) case ".rar": return extractAndFlattenRar(archivePath, extractPath) default: return fmt.Errorf("不支持的压缩格式:%s", ext) } } func decodeFilenameByByte(nameBytes []byte) (string, error) { // 创建一个 GBK 解码器 decoder := mahonia.NewDecoder("gbk") // 将字节切片解码为字符串 decodedName := decoder.ConvertString(string(nameBytes)) return decodedName, nil } func extractAndFlattenZip(archivePath, extractPath string) error { r, err := zip.OpenReader(archivePath) if err != nil { return err } log.Println("---archivePath", archivePath) defer r.Close() var decodeName string for _, f := range r.File { // path := filepath.Join(extractPath, f.Name) // log.Println("~~~~~~~~", f.Name) if f.Flags == 0 { i := bytes.NewReader([]byte(f.Name)) decoder := transform.NewReader(i, simplifiedchinese.GB18030.NewDecoder()) content, _ := ioutil.ReadAll(decoder) decodeName = string(content) f.Name = decodeName } else { decodeName = f.Name } path := filepath.Join(extractPath, decodeName) if f.FileInfo().IsDir() { os.MkdirAll(path, os.ModePerm) continue } fileReader, err := f.Open() if err != nil { return err } targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) if err != nil { fileReader.Close() return err } _, err = io.Copy(targetFile, fileReader) fileReader.Close() targetFile.Close() if err != nil { return err } baseName := filepath.Base(f.Name) ext := filepath.Ext(baseName) //没有外层目录 取压缩包名称 mulu := filepath.Base(filepath.Dir(f.Name)) if filepath.Base(filepath.Dir(f.Name)) == "." { muluarr := strings.Split(archivePath, `/`) if len(muluarr) > 0 { mulu = muluarr[len(muluarr)-1] muluarr2 := strings.Split(mulu, ".") muluarr3 := strings.Split(muluarr2[0], "_") mulu = strings.Join(muluarr3[0:len(muluarr3)-1], "_") } } //newName := filepath.Join(extractPath, fmt.Sprintf("%s_%s%s", filepath.Base(filepath.Dir(f.Name)), strings.TrimSuffix(baseName, ext), ext)) newName, err := decodeFilename(filepath.Join(extractPath, fmt.Sprintf("%s_%s%s", mulu, strings.TrimSuffix(baseName, ext), ext))) if err != nil { return err } err = os.Rename(path, newName) if err != nil { return err } } return nil } func extractAndFlattenRar(archivePath, extractPath string) error { rf, err := os.Open(archivePath) if err != nil { log.Println("rar1 err:", err) return err } defer rf.Close() reader, err := rardecode.NewReader(rf, "") if err != nil { return err } for { header, err := reader.Next() if err != nil { if err.Error() == "EOF" { break } return err } path := filepath.Join(extractPath, header.Name) path = strings.ReplaceAll(path, `\`, `/`) log.Println("===", path) header.Name = strings.ReplaceAll(header.Name, `\`, `/`) headerName := header.Name if arr := strings.Split(headerName, "/"); len(arr) > 0 { headerName = arr[len(arr)-1] path = strings.ReplaceAll(path, header.Name, headerName) } if header.IsDir { err = os.MkdirAll(path, os.ModePerm) if err != nil { return err } continue } file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, header.Mode().Perm()) if err != nil { log.Println("rar err5:", err) return err } _, err = io.Copy(file, reader) file.Close() if err != nil { log.Println("rar err2:", err) return err } baseName := filepath.Base(header.Name) ext := filepath.Ext(baseName) //没有外层目录 取压缩包名称 mulu := filepath.Base(filepath.Dir(header.Name)) if filepath.Base(filepath.Dir(header.Name)) == "." { muluarr := strings.Split(archivePath, `/`) if len(muluarr) > 0 { mulu = muluarr[len(muluarr)-1] muluarr2 := strings.Split(mulu, ".") muluarr3 := strings.Split(muluarr2[0], "_") mulu = strings.Join(muluarr3[0:len(muluarr3)-1], "_") } } //newName := filepath.Join(extractPath, fmt.Sprintf("%s_%s%s", filepath.Base(filepath.Dir(header.Name)), strings.TrimSuffix(baseName, ext), ext)) newName, err := decodeFilename(filepath.Join(extractPath, fmt.Sprintf("%s_%s%s", mulu, strings.TrimSuffix(baseName, ext), ext))) if err != nil { log.Println("rar err3:", err) return err } err = os.Rename(path, newName) if err != nil { log.Println("rar err4:", err) return err } } log.Println("+++++++++", extractPath) return nil } // 获取数据目录 func getRemoteFilePath_forunzip(webdav, user, secert, remote string) { log.Println("准备下载 ", remote, cf.YusuanInfo) client := gowebdav.NewAuthClient(webdav, gowebdav.NewAutoAuth(user, secert)) client.Connect() // 获取根目录列表 entries, err := client.ReadDir(remote) if err != nil { log.Fatal(err) } // 遍历目录结构 for _, entry := range entries { log.Println(remote + "/" + entry.Name()) if entry.IsDir() { // 如果是目录,则递归遍历子目录 readDirRecursive_forunzip(client, remote+"/"+entry.Name()) } } log.Println(fmt.Sprintf("读取文件总数量为:%d", filenum)) } //年份_承德热河地质博物馆2024年预算公开_承德热河地质博物馆2024年预算公开说明.pdf // 递归遍历目录结构 func readDirRecursive_forunzip(client *gowebdav.Client, path string) { filenum = 0 //重置数量 entries, err := client.ReadDir(path) if err != nil { log.Fatal(err) } for _, entry := range entries { if entry.IsDir() { // 如果是目录,则递归遍历子目录 readDirRecursive_forunzip(client, path+"/"+entry.Name()) } else { filenum++ file_path := path + "/" + entry.Name() yunpanPath := path sp1 := strings.Split(file_path, "/") //路径 sp2 := strings.Split(entry.Name(), ".") //文件名称 //log.Println("sp1:", sp1) //log.Println("sp2:", sp2) if len(sp2) < 2 { continue } ext := sp2[1] extMap := map[string]bool{ "rar": true, "zip": true, } if !extMap[ext] { continue } dirpath := fmt.Sprintf("./%s", strings.ReplaceAll(strings.Join(sp1, "@#$"), ".", "")) log.Println(dirpath) //创建文件 CreateDir(dirpath) //下载 reader, err := client.ReadStream(file_path) if err != nil { log.Println("err1:", err) continue } downLoadPath := dirpath + "/" + entry.Name() fo, err := os.Create(downLoadPath) if err != nil { log.Println("err2:", err) continue } io.Copy(fo, reader) reader.Close() fo.Close() do(downLoadPath, dirpath) GetPDFandWORDandEXCEL(client, dirpath, yunpanPath) //yunpanPath } } } func GetPDFandWORDandEXCEL(client *gowebdav.Client, directory string, yunpanPath string) { log.Println("寻找目标文件:", directory) err := filepath.Walk(directory, func(path string, info os.FileInfo, err error) error { path = strings.ReplaceAll(path, `\`, `/`) if err != nil { log.Println("###err:", err) return err } // 检查文件扩展名 ext := strings.ToLower(filepath.Ext(path)) if ext == ".xlsx" || ext == ".xls" || ext == ".docx" || ext == ".doc" || ext == ".pdf" { absPath, err := filepath.Abs(path) if err != nil { log.Println("转换为绝对路径出错:", err) return nil } fmt.Println("最终文件:", absPath) UploadYunPan(client, absPath, yunpanPath) } return nil }) if err != nil { fmt.Println("Error:", err) } } func UploadYunPan(client *gowebdav.Client, localFilePath, cloudFilePath string) { log.Println("localFilePath:", localFilePath) log.Println("cloudFilePath:", cloudFilePath) localFilePath = strings.ReplaceAll(localFilePath, `\`, `/`) cloudFilePath = strings.ReplaceAll(cloudFilePath, `\`, `/`) arr := strings.Split(localFilePath, "/") if len(arr) > 0 { cloudFilePath = cloudFilePath + "/" + "2024年_" + arr[len(arr)-1] } // 打开本地文件并读取文件内容 file, err := os.Open(localFilePath) if err != nil { fmt.Println("打开本地文件失败:", err) return } defer file.Close() data, err := ioutil.ReadAll(file) if err != nil { fmt.Println("读取本地文件内容失败:", err) return } // 将文件上传到云盘 err = client.Write(cloudFilePath, data, 0644) if err != nil { fmt.Println("上传文件到云盘失败:", err) return } fmt.Println("文件上传成功!") } func CreateDir(dirPath string) { _, err := os.Stat(dirPath) if os.IsNotExist(err) { err := os.Mkdir(dirPath, os.ModePerm) if err != nil { fmt.Printf("创建文件夹出错:%v\n", err) return } fmt.Println("文件夹创建成功!") } } func DelDir(dirPath string) { os.RemoveAll(dirPath) }