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 (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"godo/libs"
"io"
@ -45,7 +44,7 @@ const (
type FileChunk struct {
ChunkIndex int `json:"chunk_index"`
Data string `json:"data"`
Data []byte `json:"data"`
Checksum uint32 `json:"checksum"`
Timestamp time.Time `json:"timestamp"`
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 {
log.Fatalf("Failed to read file chunk: %v", err)
}
encodedData := base64.StdEncoding.EncodeToString(chunkData[:n])
// 创建文件块
chunk := FileChunk{
ChunkIndex: index,
Data: encodedData,
Data: chunkData[:n],
Checksum: calculateChecksum(chunkData[:n]),
Timestamp: time.Now(),
Filename: filepath.Base(file.Name()),
Filesize: fSize,
}
chunkJson, err := json.Marshal(chunk)
if err != nil {
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)
}
message.Message = chunk
sendData(message, toIp)
fmt.Printf("发送文件块 %d 到 %s 成功\n", index, toIp)
}(i)
@ -219,18 +200,6 @@ func SendFile(file *os.File, numChunks int, toIp string, fSize int64, message Ud
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) {
port := "56780"
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) {
chunkStr, ok := msg.Message.(string)
messageMap, ok := msg.Message.(map[string]interface{})
if !ok {
return "", errors.New("invalid message type")
}
// Base64解码
chunkJson, err := base64.StdEncoding.DecodeString(chunkStr)
if err != nil {
return "", fmt.Errorf("failed to decode base64 message: %v", err)
return "", fmt.Errorf("invalid message type: expected map[string]interface{}, got %T", msg.Message)
}
// 从 map 中提取 FileChunk 字段
var chunk FileChunk
if err := json.Unmarshal(chunkJson, &chunk); err != nil {
return "", fmt.Errorf("failed to unmarshal FileChunk: %v", err)
}
// 验证校验和
chunkData, err := base64.StdEncoding.DecodeString(chunk.Data)
chunk, err := extractFileChunkFromMap(messageMap)
if err != nil {
return "", fmt.Errorf("failed to decode base64 chunk data: %v", 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")
return "", err
}
// 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()
if err != nil {
@ -318,13 +276,13 @@ func ReceiveFile(msg UdpMessage) (string, error) {
defer file.Close()
// 写入数据
n, err := file.Write(chunkData)
n, err := file.Write(chunk.Data)
if err != nil {
log.Printf("Failed to write data to file: %v", err)
return "", fmt.Errorf("failed to write data to file")
}
if n != len(chunkData) {
log.Printf("Incomplete write: wrote %d bytes, expected %d bytes", n, len(chunkData))
if n != len(chunk.Data) {
log.Printf("Incomplete write: wrote %d bytes, expected %d bytes", n, len(chunk.Data))
return "", fmt.Errorf("incomplete write")
}
@ -348,3 +306,24 @@ func calculateChecksum(data []byte) uint32 {
}
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