main.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package main
  2. import (
  3. "archive/zip"
  4. "flag"
  5. "fmt"
  6. "io"
  7. "os"
  8. "path/filepath"
  9. "strings"
  10. )
  11. // Unzip 解压 zip 文件到指定目录
  12. func Unzip(src, dest string) error {
  13. r, err := zip.OpenReader(src)
  14. if err != nil {
  15. return err
  16. }
  17. defer func(r *zip.ReadCloser) {
  18. err := r.Close()
  19. if err != nil {
  20. fmt.Println("关闭 zip 文件失败:", err)
  21. }
  22. }(r)
  23. for _, f := range r.File {
  24. fpath := filepath.Join(dest, f.Name)
  25. // 检查文件夹层级,防止目录遍历漏洞
  26. if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
  27. return fmt.Errorf("非法文件路径: %s", fpath)
  28. }
  29. if f.FileInfo().IsDir() {
  30. // 创建文件夹
  31. if err := os.MkdirAll(fpath, os.ModePerm); err != nil {
  32. return err
  33. }
  34. continue
  35. }
  36. // 创建包含文件的父级目录
  37. if err := os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
  38. return err
  39. }
  40. // 打开目标文件
  41. outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
  42. if err != nil {
  43. return err
  44. }
  45. defer func(outFile *os.File) {
  46. err := outFile.Close()
  47. if err != nil {
  48. fmt.Println("关闭目标文件失败:", err)
  49. }
  50. }(outFile)
  51. // 打开 zip 内的文件
  52. rc, err := f.Open()
  53. if err != nil {
  54. return err
  55. }
  56. defer func(rc io.ReadCloser) {
  57. err := rc.Close()
  58. if err != nil {
  59. fmt.Println("关闭 zip 文件失败:", err)
  60. }
  61. }(rc)
  62. // 将内容复制到目标文件
  63. if _, err := io.Copy(outFile, rc); err != nil {
  64. return err
  65. }
  66. }
  67. return nil
  68. }
  69. func main() {
  70. // 定义命令行参数
  71. src := flag.String("f", "", "源 ZIP 文件路径")
  72. dest := flag.String("d", "", "解压到的目标文件夹路径")
  73. // 解析命令行参数
  74. flag.Parse()
  75. // 检查参数是否提供
  76. if *src == "" || *dest == "" {
  77. fmt.Println("用法: go run main.go -f <压缩包路径> -d <解压路径>")
  78. return
  79. }
  80. err := Unzip(*src, *dest)
  81. if err != nil {
  82. fmt.Println("解压失败:", err)
  83. } else {
  84. fmt.Println("解压成功!")
  85. }
  86. }