Browse Source

change file

master
godo 9 months ago
parent
commit
55bc48fa06
  1. 87
      godo/localchat/file.go

87
godo/localchat/file.go

@ -26,6 +26,7 @@ package localchat
import ( import (
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"godo/libs" "godo/libs"
"io" "io"
@ -168,7 +169,6 @@ func handleDirectory(dirPath string, toIp string, message UdpMessage) {
} }
func SendFile(file *os.File, numChunks int, toIp string, fSize int64, message UdpMessage) { func SendFile(file *os.File, numChunks int, toIp string, fSize int64, message UdpMessage) {
var wg sync.WaitGroup var wg sync.WaitGroup
mu := &sync.Mutex{}
// 逐块读取文件并发送 // 逐块读取文件并发送
for i := 0; i < numChunks; i++ { for i := 0; i < numChunks; i++ {
@ -182,6 +182,7 @@ func SendFile(file *os.File, numChunks int, toIp string, fSize int64, message Ud
log.Fatalf("Failed to read file chunk: %v", err) log.Fatalf("Failed to read file chunk: %v", err)
} }
encodedData := base64.StdEncoding.EncodeToString(chunkData[:n]) encodedData := base64.StdEncoding.EncodeToString(chunkData[:n])
// 创建文件块 // 创建文件块
chunk := FileChunk{ chunk := FileChunk{
ChunkIndex: index, ChunkIndex: index,
@ -191,49 +192,70 @@ func SendFile(file *os.File, numChunks int, toIp string, fSize int64, message Ud
Filename: filepath.Base(file.Name()), Filename: filepath.Base(file.Name()),
Filesize: fSize, Filesize: fSize,
} }
chunkJson, err := json.Marshal(chunk)
if err != nil {
log.Fatalf("Failed to marshal chunk: %v", err)
}
message.Message = base64.StdEncoding.EncodeToString(chunkJson)
// 将文件块转换为 JSON 格式 chunkJson, err := json.Marshal(chunk)
data, err := json.Marshal(message)
if err != nil { if err != nil {
log.Fatalf("Failed to marshal chunk: %v", err) log.Fatalf("Failed to marshal chunk: %v", err)
} }
// 发送文件块 // 确保每个数据包的大小不超过限制
port := "56780" maxPacketSize := 65000
addr, err := net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%s", toIp, port)) if len(chunkJson) > maxPacketSize {
if err != nil { // 分割数据包
log.Fatalf("Failed to resolve UDP address: %v", err) chunks := splitChunkJson(chunkJson, maxPacketSize)
} for _, subChunkJson := range chunks {
message.Message = base64.StdEncoding.EncodeToString(subChunkJson)
conn, err := net.DialUDP("udp4", nil, addr) sendData(message, toIp)
if err != nil { }
log.Fatalf("Failed to dial UDP address: %v", err) } else {
} message.Message = base64.StdEncoding.EncodeToString(chunkJson)
defer conn.Close() sendData(message, toIp)
_, err = conn.Write(data)
if err != nil {
log.Printf("Failed to write data: %v", err)
} }
mu.Lock()
fmt.Printf("发送文件块 %d 到 %s 成功\n", index, toIp) fmt.Printf("发送文件块 %d 到 %s 成功\n", index, toIp)
mu.Unlock()
}(i) }(i)
} }
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) {
port := "56780"
addr, err := net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%s", toIp, port))
if err != nil {
log.Fatalf("Failed to resolve UDP address: %v", err)
}
conn, err := net.DialUDP("udp4", nil, addr)
if err != nil {
log.Fatalf("Failed to dial UDP address: %v", err)
}
defer conn.Close()
data, _ := json.Marshal(message)
_, err = conn.Write(data)
if err != nil {
log.Printf("Failed to write data: %v", err)
}
}
func ReceiveFile(msg UdpMessage) (string, error) { func ReceiveFile(msg UdpMessage) (string, error) {
chunkStr, ok := msg.Message.(string) chunkStr, ok := msg.Message.(string)
if !ok { if !ok {
return "", fmt.Errorf("invalid message type") return "", errors.New("invalid message type")
} }
// Base64解码 // Base64解码
chunkJson, err := base64.StdEncoding.DecodeString(chunkStr) chunkJson, err := base64.StdEncoding.DecodeString(chunkStr)
if err != nil { if err != nil {
@ -245,24 +267,25 @@ func ReceiveFile(msg UdpMessage) (string, error) {
if err := json.Unmarshal(chunkJson, &chunk); err != nil { if err := json.Unmarshal(chunkJson, &chunk); err != nil {
return "", fmt.Errorf("failed to unmarshal FileChunk: %v", err) return "", fmt.Errorf("failed to unmarshal FileChunk: %v", err)
} }
// 验证校验和
chunkData, err := base64.StdEncoding.DecodeString(chunk.Data) 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 "", fmt.Errorf("failed to decode base64 chunk data: %v", err)
} }
// 验证校验和
calculatedChecksum := calculateChecksum(chunkData) calculatedChecksum := calculateChecksum(chunkData)
if calculatedChecksum != chunk.Checksum { if calculatedChecksum != chunk.Checksum {
fmt.Printf("Checksum mismatch for chunk %d from %s\n", chunk.ChunkIndex, msg.IP) fmt.Printf("Checksum mismatch for chunk %d from %s\n", chunk.ChunkIndex, msg.IP)
return "", fmt.Errorf("checksum mismatch") return "", fmt.Errorf("checksum mismatch")
} }
// 创建接收文件的目录
baseDir, err := libs.GetOsDir() baseDir, err := libs.GetOsDir()
if err != nil { if err != nil {
log.Printf("Failed to get OS directory: %v", err) log.Printf("Failed to get OS directory: %v", err)
return "", fmt.Errorf("failed to get OS directory") return "", fmt.Errorf("failed to get OS directory")
} }
// 创建接收文件的目录
resPath := filepath.Join("C", "Users", "Reciv", time.Now().Format("2006-01-02")) resPath := filepath.Join("C", "Users", "Reciv", time.Now().Format("2006-01-02"))
receiveDir := filepath.Join(baseDir, resPath) receiveDir := filepath.Join(baseDir, resPath)
if !libs.PathExists(receiveDir) { if !libs.PathExists(receiveDir) {
@ -294,12 +317,6 @@ func ReceiveFile(msg UdpMessage) (string, error) {
} }
defer file.Close() defer file.Close()
// 写入数据前检查 Data 是否为空
if len(chunkData) == 0 {
fmt.Println("Chunk data is empty.")
return "", fmt.Errorf("chunk data is empty")
}
// 写入数据 // 写入数据
n, err := file.Write(chunkData) n, err := file.Write(chunkData)
if err != nil { if err != nil {

Loading…
Cancel
Save