FileUpload.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package handler
  2. import (
  3. "errors"
  4. "fmt"
  5. "io/fs"
  6. "os"
  7. "path/filepath"
  8. "strings"
  9. "sync"
  10. )
  11. type PathInfo struct {
  12. Dirs []string // 目录路径(包含所有层级)
  13. Files []string // 文件路径
  14. }
  15. var pathPool = sync.Pool{
  16. New: func() interface{} {
  17. return &PathInfo{
  18. Dirs: make([]string, 0, 1024), // 预分配容量
  19. Files: make([]string, 0, 4096),
  20. }
  21. },
  22. }
  23. func GoHeavy(info *PathInfo) (PathInfo, error) {
  24. m := make(map[string]bool)
  25. for i := range info.Files {
  26. path := info.Files[i]
  27. lastIndex := strings.LastIndex(path, "/")
  28. if lastIndex == -1 {
  29. lastIndex = strings.LastIndex(path, "\\")
  30. }
  31. if lastIndex == -1 {
  32. continue
  33. }
  34. //if _, ok := m[path[:lastIndex]]; !ok {
  35. // fmt.Println(path[:lastIndex])
  36. //}
  37. m[path[:lastIndex]] = true
  38. }
  39. var dirs = make([]string, 0, len(m))
  40. fmt.Println(len(info.Dirs))
  41. for i := range info.Dirs {
  42. path := info.Dirs[i]
  43. if !m[path] {
  44. fmt.Println(info.Dirs[i])
  45. dirs = append(dirs, info.Dirs[i])
  46. }
  47. }
  48. info.Dirs = dirs
  49. return *info, nil
  50. }
  51. func GetPathInfo(root string) (*PathInfo, error) {
  52. //获取文件名
  53. index := strings.LastIndex(root, "/")
  54. if index == -1 {
  55. index = strings.LastIndex(root, "\\")
  56. }
  57. //RootFileName := ""
  58. //if index == -1 {
  59. // RootFileName = root
  60. //} else {
  61. // RootFileName = root[:index+1]
  62. //}
  63. // 复用对象减少内存分配[9](@ref)
  64. info := pathPool.Get().(*PathInfo)
  65. // 路径有效性校验[5,6](@ref)
  66. root = filepath.Clean(root)
  67. stat, err := os.Stat(root)
  68. if err != nil {
  69. if errors.Is(err, fs.ErrNotExist) {
  70. return nil, &os.PathError{Op: "stat", Path: root, Err: err} // 增强错误信息[8](@ref)
  71. }
  72. return nil, err
  73. }
  74. // 文件直接返回[4](@ref)
  75. if !stat.IsDir() {
  76. info.Files = append(info.Files, root)
  77. return info, nil
  78. }
  79. // 使用WalkDir优化遍历性能[4,9](@ref)
  80. err = filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
  81. if err != nil {
  82. // 处理遍历错误但继续执行[7](@ref)
  83. if errors.Is(err, fs.ErrPermission) {
  84. return nil // 跳过权限错误
  85. }
  86. return err
  87. }
  88. // 排除根目录自身
  89. if path == root {
  90. return nil
  91. }
  92. // 动态扩容检测[9](@ref)
  93. if len(info.Dirs)+len(info.Files) > 1e8 {
  94. return errors.New("超出内存安全阈值(1,000,000条路径)")
  95. }
  96. //fmt.Println(path[len(RootFileName):])
  97. if d.IsDir() {
  98. info.Dirs = append(info.Dirs, path)
  99. } else {
  100. info.Files = append(info.Files, path)
  101. }
  102. return nil
  103. })
  104. if err != nil {
  105. return nil, &os.PathError{Op: "walk", Path: root, Err: err} // 错误包装[6](@ref)
  106. }
  107. return info, nil
  108. }
  109. // 流式处理版本(适用于超大数据集)
  110. func StreamPathInfo(root string) (<-chan string, <-chan error) {
  111. paths := make(chan string, 1000)
  112. errs := make(chan error, 1)
  113. go func() {
  114. defer close(paths)
  115. defer close(errs)
  116. err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
  117. if err != nil {
  118. return err
  119. }
  120. if path != root {
  121. select {
  122. case paths <- path:
  123. default:
  124. return errors.New("消费者处理过慢")
  125. }
  126. }
  127. return nil
  128. })
  129. if err != nil {
  130. errs <- &os.PathError{Op: "stream", Path: root, Err: err}
  131. }
  132. }()
  133. return paths, errs
  134. }