UploadFileHandler.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. package server
  2. import (
  3. "encoding/binary"
  4. "errors"
  5. "fmt"
  6. "io/fs"
  7. "io/ioutil"
  8. "os"
  9. "path/filepath"
  10. "strings"
  11. "sync"
  12. )
  13. type PathInfo struct {
  14. Dirs []string // 目录路径(包含所有层级)
  15. Files []string // 文件路径
  16. }
  17. var pathPool = sync.Pool{
  18. New: func() interface{} {
  19. return &PathInfo{
  20. Dirs: make([]string, 0, 1024), // 预分配容量
  21. Files: make([]string, 0, 4096),
  22. }
  23. },
  24. }
  25. func GetPathInfo(root string) (*PathInfo, error) {
  26. //获取文件名
  27. index := strings.LastIndex(root, "/")
  28. if index == -1 {
  29. index = strings.LastIndex(root, "\\")
  30. }
  31. // 复用对象减少内存分配[9](@ref)
  32. info := pathPool.Get().(*PathInfo)
  33. // 路径有效性校验[5,6](@ref)
  34. root = filepath.Clean(root)
  35. stat, err := os.Stat(root)
  36. if err != nil {
  37. if errors.Is(err, fs.ErrNotExist) {
  38. return nil, &os.PathError{Op: "stat", Path: root, Err: err} // 增强错误信息[8](@ref)
  39. }
  40. return nil, err
  41. }
  42. // 文件直接返回[4](@ref)
  43. if !stat.IsDir() {
  44. info.Files = append(info.Files, root)
  45. return info, nil
  46. }
  47. // 使用WalkDir优化遍历性能[4,9](@ref)
  48. err = filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
  49. if err != nil {
  50. // 处理遍历错误但继续执行[7](@ref)
  51. if errors.Is(err, fs.ErrPermission) {
  52. return nil // 跳过权限错误
  53. }
  54. return err
  55. }
  56. // 排除根目录自身
  57. if path == root {
  58. return nil
  59. }
  60. // 动态扩容检测[9](@ref)
  61. if len(info.Dirs)+len(info.Files) > 1e8 {
  62. return errors.New("超出内存安全阈值(1,000,000条路径)")
  63. }
  64. //fmt.Println(path[len(RootFileName):])
  65. if d.IsDir() {
  66. info.Dirs = append(info.Dirs, path)
  67. } else {
  68. info.Files = append(info.Files, path)
  69. }
  70. return nil
  71. })
  72. if err != nil {
  73. return nil, &os.PathError{Op: "walk", Path: root, Err: err} // 错误包装[6](@ref)
  74. }
  75. return info, nil
  76. }
  77. type FileHandler struct{}
  78. func (handler FileHandler) ReadFileToCommand(filePath string) {
  79. _, err := GetPathInfo(filePath)
  80. if err != nil {
  81. fmt.Println(err)
  82. }
  83. }
  84. func (handler FileHandler) CreateCommand(path string) error {
  85. // 获取文件信息
  86. fileInfo, err := os.Stat(path)
  87. if err != nil {
  88. return fmt.Errorf("路径获取失败: %v", err)
  89. }
  90. // 判断文件类型
  91. if fileInfo.IsDir() {
  92. // 处理目录
  93. fmt.Printf("文件夹内容 [%s]:\n", path)
  94. files, err := ioutil.ReadDir(path)
  95. if err != nil {
  96. return fmt.Errorf("目录读取失败: %v", err)
  97. }
  98. for _, f := range files {
  99. fmt.Println(f.Name())
  100. }
  101. } else {
  102. // 处理文件
  103. fmt.Printf("文件内容 [%s]:\n", path)
  104. data, err := ioutil.ReadFile(path)
  105. if err != nil {
  106. return fmt.Errorf("文件读取失败: %v", err)
  107. }
  108. // 打印前512字节的十六进制预览
  109. maxPreview := 512
  110. if len(data) < maxPreview {
  111. maxPreview = len(data)
  112. }
  113. fmt.Printf("大小: %d 字节\n", len(data))
  114. fmt.Printf("前%d字节预览(HEX):\n%x", maxPreview, data[:maxPreview])
  115. }
  116. return nil
  117. }
  118. func CreateDirCommand(info os.FileInfo, baseUrl string, transactionId string) {
  119. bytes := []byte{
  120. 0x00,
  121. }
  122. for i := 0; i < 32; i++ {
  123. bytes = append(bytes, byte(i+3))
  124. }
  125. var fileName = info.Name()
  126. //文件名长度
  127. bytes = binary.BigEndian.AppendUint32(bytes, uint32(len(fileName)))
  128. //文件名
  129. bytes = append(bytes, []byte(fileName)...)
  130. //文件大小
  131. bytes = binary.BigEndian.AppendUint64(bytes, uint64(info.Size()))
  132. var path = "file/" + fileName
  133. bytes = binary.BigEndian.AppendUint32(bytes, uint32(len(path)))
  134. //文件路径
  135. bytes = append(bytes, []byte(path)...)
  136. //分片大小
  137. bytes = binary.BigEndian.AppendUint32(bytes, uint32(0))
  138. //创建时间
  139. bytes = binary.BigEndian.AppendUint64(bytes, uint64(1999))
  140. //修改时间
  141. bytes = binary.BigEndian.AppendUint64(bytes, uint64(19999))
  142. //最后访问时间
  143. bytes = binary.BigEndian.AppendUint64(bytes, uint64(199999))
  144. }
  145. func (handler FileHandler) ParsingByteArray() {}