Handler.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. package server
  2. import (
  3. "encoding/binary"
  4. "errors"
  5. "file-manger-server/config"
  6. "file-manger-server/db"
  7. "file-manger-server/domain"
  8. "fmt"
  9. "io"
  10. "os"
  11. "strings"
  12. )
  13. type ReturnCommand interface {
  14. Return() []byte
  15. }
  16. func HandlerReceiveFile(info *ConnInfo, msg []byte) {
  17. var commandId = msg[0]
  18. //事务id解析
  19. var transactionId = msg[1:33]
  20. fmt.Println(ToHexBytes(transactionId))
  21. var tranId = ToHexBytes(transactionId)
  22. if commandId == 0 {
  23. InfoTransaction(info, msg, tranId)
  24. } else if commandId == 1 {
  25. err := InfoTransactionSplit(info, msg, tranId)
  26. fmt.Println(err)
  27. }
  28. //1. 接收基本元数据(事务id(32),len文件名(4+?),文件大小(8),相对路径(4+?),分片数量(按特定大小进行分片)(4),创建时间(8),修改时间(8),访问时间(8)=> 返回事务id,如果重复则返回错误 76+?
  29. //2. 接收包含事务id的分片内容
  30. }
  31. // InfoTransaction 获取的事务数据内容
  32. func InfoTransaction(info *ConnInfo, msg []byte, transactionId string) error {
  33. fileUser, err := db.FileUserDao{}.Get(transactionId)
  34. if err != nil {
  35. return errors.New("FileUser transactionId is not found")
  36. }
  37. if fileUser.UserId == 0 {
  38. return errors.New("FileUser userId is not found")
  39. }
  40. var fileNameLength = binary.BigEndian.Uint32(msg[33:37])
  41. var filename = string(msg[37 : 37+fileNameLength])
  42. var fileSize = int64(binary.BigEndian.Uint64(msg[37+fileNameLength : 45+fileNameLength]))
  43. var pathLength = binary.BigEndian.Uint32(msg[45+fileNameLength : 49+fileNameLength])
  44. var path = string(msg[49+fileNameLength : 49+fileNameLength+pathLength])
  45. path = fmt.Sprint(config.Conf.File.Upload.Path, "/", fileUser.UserId, "/", transactionId, "/", path)
  46. var splitCount = binary.BigEndian.Uint32(msg[49+fileNameLength+pathLength : 53+fileNameLength+pathLength])
  47. var createTime = binary.BigEndian.Uint64(msg[53+fileNameLength+pathLength : 61+fileNameLength+pathLength])
  48. var modifyTime = binary.BigEndian.Uint64(msg[61+fileNameLength+pathLength : 69+fileNameLength+pathLength])
  49. var accessTime = binary.BigEndian.Uint64(msg[69+fileNameLength+pathLength : 77+fileNameLength+pathLength])
  50. Type := ""
  51. if fileSize == -1 {
  52. Type = "folder"
  53. } else {
  54. Type = "file"
  55. }
  56. ExtensionName := ""
  57. index := strings.Index(filename, ".")
  58. if index != -1 {
  59. ExtensionName = filename[index+1:]
  60. }
  61. file := domain.File{
  62. Name: filename,
  63. Url: path,
  64. Size: fileSize,
  65. Type: Type,
  66. MD5: "",
  67. TransactionId: transactionId,
  68. Extension: ExtensionName,
  69. Access: domain.FileAccess{},
  70. CreateUser: 0,
  71. CreateTime: int64(createTime),
  72. UpdateTime: int64(modifyTime),
  73. }
  74. //添加元素
  75. db.FileDao{}.Insert(file)
  76. //递归创建前面的文件夹
  77. lastIndex := strings.LastIndex(path, "/")
  78. if lastIndex != -1 {
  79. err := os.MkdirAll(path[:lastIndex], 0755)
  80. if err != nil {
  81. return err
  82. }
  83. }
  84. if splitCount == 0 {
  85. if fileSize >= 0 {
  86. //打开文件
  87. openFile, err := os.Create(path)
  88. if err != nil {
  89. fmt.Println("err:", err)
  90. }
  91. defer openFile.Close()
  92. var content = msg[77+fileNameLength+pathLength:]
  93. openFile.Write(content)
  94. } else {
  95. err := os.Mkdir(path, 0755)
  96. if err != nil {
  97. fmt.Println(err)
  98. }
  99. }
  100. } else {
  101. // 创建一个空文件
  102. file, err := os.Create(path)
  103. if err != nil {
  104. fmt.Println("Error creating file:", err)
  105. return err
  106. }
  107. defer file.Close() // 确保在函数结束时关闭文件
  108. fmt.Println("file size :", fileSize)
  109. err = file.Truncate(fileSize)
  110. if err != nil {
  111. fmt.Println("Error setting file size:", err)
  112. return err
  113. }
  114. }
  115. // 返回状态信息
  116. //info.conn.Write()
  117. fmt.Println(fmt.Sprintf("事务id:%d\n文件名:%s\n文件大小:%d\n相对路径:%s\n分片数量:%d\n创建时间:%d\n修改时间:%d\n访问时间:%d", transactionId, filename, fileSize, path, splitCount, createTime, modifyTime, accessTime))
  118. return nil
  119. }
  120. // InfoTransactionSplit 获取的事务数据内容
  121. func InfoTransactionSplit(info *ConnInfo, msg []byte, transactionId string) error {
  122. fileUser, err := db.FileUserDao{}.Get(transactionId)
  123. if err != nil {
  124. return errors.New("FileUser transactionId is not found")
  125. }
  126. if fileUser.UserId == 0 {
  127. return errors.New("FileUser userId is not found")
  128. }
  129. var splitNum = binary.BigEndian.Uint32(msg[33:37])
  130. var pathLength = binary.BigEndian.Uint32(msg[37:41])
  131. var path = string(msg[41 : 41+pathLength])
  132. path = fmt.Sprint(config.Conf.File.Upload.Path, "/", fileUser.UserId, "/", transactionId, "/", path)
  133. var content = msg[41+pathLength:]
  134. err = insertDataAtPosition(path, int64(splitNum*1024), content)
  135. return err
  136. // 返回状态信息
  137. //info.conn.Write()
  138. //fmt.Println(fmt.Sprintf("事务id:%d\n文件名:%s\n文件大小:%d\n相对路径:%s\n分片数量:%d\n创建时间:%d\n修改时间:%d\n访问时间:%d", transactionId, filename, fileSize, path, splitCount, createTime, modifyTime, accessTime))
  139. }
  140. var sign = 0
  141. func insertDataAtPosition(filePath string, position int64, data []byte) error {
  142. // 1. 打开文件
  143. file, err := os.OpenFile(filePath, os.O_RDWR, 0644)
  144. if err != nil {
  145. return fmt.Errorf("error opening file: %v", err)
  146. }
  147. defer file.Close()
  148. // 2. 获取文件元数据
  149. fileInfo, err := file.Stat()
  150. if err != nil {
  151. return fmt.Errorf("error getting file info: %v", err)
  152. }
  153. fileSize := fileInfo.Size()
  154. // 3. 校验插入位置
  155. if position > fileSize {
  156. return fmt.Errorf("position exceeds file size")
  157. }
  158. // 4. 计算需要移动的数据量
  159. //originalDataLength := fileSize - position
  160. insertLength := int64(len(data))
  161. // 5. 分块移动原始数据(从后往前处理)
  162. //var offset int64 = position
  163. //for offset > 0 {
  164. // 定位读取位置
  165. readPos := position
  166. // 读取块数据
  167. buffer := make([]byte, insertLength)
  168. _, err = file.ReadAt(buffer, readPos)
  169. if err != nil && err != io.EOF {
  170. return fmt.Errorf("read block error: %v", err)
  171. }
  172. sign += 1
  173. fmt.Println("buffer len :", len(buffer), " sign => ", sign)
  174. // 写入新位置
  175. _, err = file.WriteAt(buffer, readPos)
  176. if err != nil {
  177. return fmt.Errorf("write block error: %v", err)
  178. }
  179. fmt.Println("writePos ind :", readPos+int64(len(buffer)))
  180. //}
  181. // 6. 写入新数据
  182. _, err = file.WriteAt(data, position)
  183. if err != nil {
  184. return fmt.Errorf("write data error: %v", err)
  185. }
  186. // 7. 扩展文件大小(如果需要)
  187. //newSize := fileSize + insertLength
  188. //if newSize > fileSize {
  189. // if err := file.Truncate(newSize); err != nil {
  190. // return fmt.Errorf("truncate error: %v", err)
  191. // }
  192. //}
  193. return nil
  194. }
  195. func ToHexBytes(bytes []byte) string {
  196. var hexBytes string
  197. for b := range bytes {
  198. hexBytes = fmt.Sprint(hexBytes, fmt.Sprintf("%02X", bytes[b]))
  199. }
  200. return strings.TrimSpace(hexBytes)
  201. }