| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- package server
- import (
- "encoding/binary"
- "errors"
- "file-manger-server/config"
- "file-manger-server/db"
- "file-manger-server/domain"
- "fmt"
- "io"
- "os"
- "strings"
- )
- type ReturnCommand interface {
- Return() []byte
- }
- func HandlerReceiveFile(info *ConnInfo, msg []byte) {
- var commandId = msg[0]
- //事务id解析
- var transactionId = msg[1:33]
- fmt.Println(ToHexBytes(transactionId))
- var tranId = ToHexBytes(transactionId)
- if commandId == 0 {
- InfoTransaction(info, msg, tranId)
- } else if commandId == 1 {
- err := InfoTransactionSplit(info, msg, tranId)
- fmt.Println(err)
- }
- //1. 接收基本元数据(事务id(32),len文件名(4+?),文件大小(8),相对路径(4+?),分片数量(按特定大小进行分片)(4),创建时间(8),修改时间(8),访问时间(8)=> 返回事务id,如果重复则返回错误 76+?
- //2. 接收包含事务id的分片内容
- }
- // InfoTransaction 获取的事务数据内容
- func InfoTransaction(info *ConnInfo, msg []byte, transactionId string) error {
- fileUser, err := db.FileUserDao{}.Get(transactionId)
- if err != nil {
- return errors.New("FileUser transactionId is not found")
- }
- if fileUser.UserId == 0 {
- return errors.New("FileUser userId is not found")
- }
- var fileNameLength = binary.BigEndian.Uint32(msg[33:37])
- var filename = string(msg[37 : 37+fileNameLength])
- var fileSize = int64(binary.BigEndian.Uint64(msg[37+fileNameLength : 45+fileNameLength]))
- var pathLength = binary.BigEndian.Uint32(msg[45+fileNameLength : 49+fileNameLength])
- var path = string(msg[49+fileNameLength : 49+fileNameLength+pathLength])
- path = fmt.Sprint(config.Conf.File.Upload.Path, "/", fileUser.UserId, "/", transactionId, "/", path)
- var splitCount = binary.BigEndian.Uint32(msg[49+fileNameLength+pathLength : 53+fileNameLength+pathLength])
- var createTime = binary.BigEndian.Uint64(msg[53+fileNameLength+pathLength : 61+fileNameLength+pathLength])
- var modifyTime = binary.BigEndian.Uint64(msg[61+fileNameLength+pathLength : 69+fileNameLength+pathLength])
- var accessTime = binary.BigEndian.Uint64(msg[69+fileNameLength+pathLength : 77+fileNameLength+pathLength])
- Type := ""
- if fileSize == -1 {
- Type = "folder"
- } else {
- Type = "file"
- }
- ExtensionName := ""
- index := strings.Index(filename, ".")
- if index != -1 {
- ExtensionName = filename[index+1:]
- }
- file := domain.File{
- Name: filename,
- Url: path,
- Size: fileSize,
- Type: Type,
- MD5: "",
- TransactionId: transactionId,
- Extension: ExtensionName,
- Access: domain.FileAccess{},
- CreateUser: 0,
- CreateTime: int64(createTime),
- UpdateTime: int64(modifyTime),
- }
- //添加元素
- db.FileDao{}.Insert(file)
- //递归创建前面的文件夹
- lastIndex := strings.LastIndex(path, "/")
- if lastIndex != -1 {
- err := os.MkdirAll(path[:lastIndex], 0755)
- if err != nil {
- return err
- }
- }
- if splitCount == 0 {
- if fileSize >= 0 {
- //打开文件
- openFile, err := os.Create(path)
- if err != nil {
- fmt.Println("err:", err)
- }
- defer openFile.Close()
- var content = msg[77+fileNameLength+pathLength:]
- openFile.Write(content)
- } else {
- err := os.Mkdir(path, 0755)
- if err != nil {
- fmt.Println(err)
- }
- }
- } else {
- // 创建一个空文件
- file, err := os.Create(path)
- if err != nil {
- fmt.Println("Error creating file:", err)
- return err
- }
- defer file.Close() // 确保在函数结束时关闭文件
- fmt.Println("file size :", fileSize)
- err = file.Truncate(fileSize)
- if err != nil {
- fmt.Println("Error setting file size:", err)
- return err
- }
- }
- // 返回状态信息
- //info.conn.Write()
- 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))
- return nil
- }
- // InfoTransactionSplit 获取的事务数据内容
- func InfoTransactionSplit(info *ConnInfo, msg []byte, transactionId string) error {
- fileUser, err := db.FileUserDao{}.Get(transactionId)
- if err != nil {
- return errors.New("FileUser transactionId is not found")
- }
- if fileUser.UserId == 0 {
- return errors.New("FileUser userId is not found")
- }
- var splitNum = binary.BigEndian.Uint32(msg[33:37])
- var pathLength = binary.BigEndian.Uint32(msg[37:41])
- var path = string(msg[41 : 41+pathLength])
- path = fmt.Sprint(config.Conf.File.Upload.Path, "/", fileUser.UserId, "/", transactionId, "/", path)
- var content = msg[41+pathLength:]
- err = insertDataAtPosition(path, int64(splitNum*1024), content)
- return err
- // 返回状态信息
- //info.conn.Write()
- //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))
- }
- var sign = 0
- func insertDataAtPosition(filePath string, position int64, data []byte) error {
- // 1. 打开文件
- file, err := os.OpenFile(filePath, os.O_RDWR, 0644)
- if err != nil {
- return fmt.Errorf("error opening file: %v", err)
- }
- defer file.Close()
- // 2. 获取文件元数据
- fileInfo, err := file.Stat()
- if err != nil {
- return fmt.Errorf("error getting file info: %v", err)
- }
- fileSize := fileInfo.Size()
- // 3. 校验插入位置
- if position > fileSize {
- return fmt.Errorf("position exceeds file size")
- }
- // 4. 计算需要移动的数据量
- //originalDataLength := fileSize - position
- insertLength := int64(len(data))
- // 5. 分块移动原始数据(从后往前处理)
- //var offset int64 = position
- //for offset > 0 {
- // 定位读取位置
- readPos := position
- // 读取块数据
- buffer := make([]byte, insertLength)
- _, err = file.ReadAt(buffer, readPos)
- if err != nil && err != io.EOF {
- return fmt.Errorf("read block error: %v", err)
- }
- sign += 1
- fmt.Println("buffer len :", len(buffer), " sign => ", sign)
- // 写入新位置
- _, err = file.WriteAt(buffer, readPos)
- if err != nil {
- return fmt.Errorf("write block error: %v", err)
- }
- fmt.Println("writePos ind :", readPos+int64(len(buffer)))
- //}
- // 6. 写入新数据
- _, err = file.WriteAt(data, position)
- if err != nil {
- return fmt.Errorf("write data error: %v", err)
- }
- // 7. 扩展文件大小(如果需要)
- //newSize := fileSize + insertLength
- //if newSize > fileSize {
- // if err := file.Truncate(newSize); err != nil {
- // return fmt.Errorf("truncate error: %v", err)
- // }
- //}
- return nil
- }
- func ToHexBytes(bytes []byte) string {
- var hexBytes string
- for b := range bytes {
- hexBytes = fmt.Sprint(hexBytes, fmt.Sprintf("%02X", bytes[b]))
- }
- return strings.TrimSpace(hexBytes)
- }
|