Browse Source

change image

master
godo 9 months ago
parent
commit
38d27d72d8
  1. 97
      godo/localchat/file.go

97
godo/localchat/file.go

@ -26,7 +26,6 @@ package localchat
import ( import (
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"godo/libs" "godo/libs"
"io" "io"
@ -45,7 +44,7 @@ const (
type FileChunk struct { type FileChunk struct {
ChunkIndex int `json:"chunk_index"` ChunkIndex int `json:"chunk_index"`
Data string `json:"data"` Data []byte `json:"data"`
Checksum uint32 `json:"checksum"` Checksum uint32 `json:"checksum"`
Timestamp time.Time `json:"timestamp"` Timestamp time.Time `json:"timestamp"`
Filename string `json:"filename"` Filename string `json:"filename"`
@ -181,36 +180,18 @@ func SendFile(file *os.File, numChunks int, toIp string, fSize int64, message Ud
if err != nil && err != io.EOF { if err != nil && err != io.EOF {
log.Fatalf("Failed to read file chunk: %v", err) log.Fatalf("Failed to read file chunk: %v", err)
} }
encodedData := base64.StdEncoding.EncodeToString(chunkData[:n])
// 创建文件块 // 创建文件块
chunk := FileChunk{ chunk := FileChunk{
ChunkIndex: index, ChunkIndex: index,
Data: encodedData, Data: chunkData[:n],
Checksum: calculateChecksum(chunkData[:n]), Checksum: calculateChecksum(chunkData[:n]),
Timestamp: time.Now(), Timestamp: time.Now(),
Filename: filepath.Base(file.Name()), Filename: filepath.Base(file.Name()),
Filesize: fSize, Filesize: fSize,
} }
chunkJson, err := json.Marshal(chunk) message.Message = chunk
if err != nil { sendData(message, toIp)
log.Fatalf("Failed to marshal chunk: %v", err)
}
// 确保每个数据包的大小不超过限制
maxPacketSize := 65000
if len(chunkJson) > maxPacketSize {
// 分割数据包
chunks := splitChunkJson(chunkJson, maxPacketSize)
for _, subChunkJson := range chunks {
message.Message = base64.StdEncoding.EncodeToString(subChunkJson)
sendData(message, toIp)
}
} else {
message.Message = base64.StdEncoding.EncodeToString(chunkJson)
sendData(message, toIp)
}
fmt.Printf("发送文件块 %d 到 %s 成功\n", index, toIp) fmt.Printf("发送文件块 %d 到 %s 成功\n", index, toIp)
}(i) }(i)
@ -219,18 +200,6 @@ func SendFile(file *os.File, numChunks int, toIp string, fSize int64, message Ud
wg.Wait() wg.Wait()
} }
func splitChunkJson(jsonData []byte, maxSize int) [][]byte {
var chunks [][]byte
for start := 0; start < len(jsonData); start += maxSize {
end := start + maxSize
if end > len(jsonData) {
end = len(jsonData)
}
chunks = append(chunks, jsonData[start:end])
}
return chunks
}
func sendData(message UdpMessage, toIp string) { func sendData(message UdpMessage, toIp string) {
port := "56780" port := "56780"
addr, err := net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%s", toIp, port)) addr, err := net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%s", toIp, port))
@ -251,34 +220,23 @@ func sendData(message UdpMessage, toIp string) {
} }
} }
func ReceiveFile(msg UdpMessage) (string, error) { func ReceiveFile(msg UdpMessage) (string, error) {
chunkStr, ok := msg.Message.(string) messageMap, ok := msg.Message.(map[string]interface{})
if !ok { if !ok {
return "", errors.New("invalid message type") return "", fmt.Errorf("invalid message type: expected map[string]interface{}, got %T", msg.Message)
}
// Base64解码
chunkJson, err := base64.StdEncoding.DecodeString(chunkStr)
if err != nil {
return "", fmt.Errorf("failed to decode base64 message: %v", err)
} }
// 从 map 中提取 FileChunk 字段 // 从 map 中提取 FileChunk 字段
var chunk FileChunk chunk, err := extractFileChunkFromMap(messageMap)
if err := json.Unmarshal(chunkJson, &chunk); err != nil {
return "", fmt.Errorf("failed to unmarshal FileChunk: %v", err)
}
// 验证校验和
chunkData, err := base64.StdEncoding.DecodeString(chunk.Data)
if err != nil { if err != nil {
return "", fmt.Errorf("failed to decode base64 chunk data: %v", err) return "", err
}
calculatedChecksum := calculateChecksum(chunkData)
if calculatedChecksum != chunk.Checksum {
fmt.Printf("Checksum mismatch for chunk %d from %s\n", chunk.ChunkIndex, msg.IP)
return "", fmt.Errorf("checksum mismatch")
} }
// calculatedChecksum := calculateChecksum(chunk.Data)
// if calculatedChecksum != chunk.Checksum {
// fmt.Printf("Checksum mismatch for chunk %d from %s\n", chunk.ChunkIndex, msg.IP)
// return "", fmt.Errorf("checksum mismatch")
// }
// 创建接收文件的目录 // 创建接收文件的目录
baseDir, err := libs.GetOsDir() baseDir, err := libs.GetOsDir()
if err != nil { if err != nil {
@ -318,13 +276,13 @@ func ReceiveFile(msg UdpMessage) (string, error) {
defer file.Close() defer file.Close()
// 写入数据 // 写入数据
n, err := file.Write(chunkData) n, err := file.Write(chunk.Data)
if err != nil { if err != nil {
log.Printf("Failed to write data to file: %v", err) log.Printf("Failed to write data to file: %v", err)
return "", fmt.Errorf("failed to write data to file") return "", fmt.Errorf("failed to write data to file")
} }
if n != len(chunkData) { if n != len(chunk.Data) {
log.Printf("Incomplete write: wrote %d bytes, expected %d bytes", n, len(chunkData)) log.Printf("Incomplete write: wrote %d bytes, expected %d bytes", n, len(chunk.Data))
return "", fmt.Errorf("incomplete write") return "", fmt.Errorf("incomplete write")
} }
@ -348,3 +306,24 @@ func calculateChecksum(data []byte) uint32 {
} }
return checksum return checksum
} }
// 从 map 中提取 FileChunk 结构体
func extractFileChunkFromMap(m map[string]interface{}) (FileChunk, error) {
chunk := FileChunk{}
// 从 map 中提取字段
chunk.ChunkIndex, _ = m["chunk_index"].(int)
dataStr, _ := m["data"].(string)
dataBytes, err := base64.StdEncoding.DecodeString(dataStr)
if err != nil {
return chunk, fmt.Errorf("failed to decode data: %v", err)
}
chunk.Data = dataBytes
chunk.Checksum, _ = m["checksum"].(uint32)
timestamp, _ := m["timestamp"].(string)
chunk.Timestamp, _ = time.Parse(time.RFC3339, timestamp)
chunk.Filename, _ = m["filename"].(string)
chunk.Filesize, _ = m["filesize"].(int64)
return chunk, nil
}

Loading…
Cancel
Save