Browse Source

change send image

master
godo 9 months ago
parent
commit
42769022ea
  1. 118
      frontend/src/stores/localchat.ts
  2. 56
      godo/localchat/file.go
  3. 184
      godo/localchat/image.go
  4. 2
      godo/localchat/server.go

118
frontend/src/stores/localchat.ts

@ -50,7 +50,7 @@ export const useLocalChatStore = defineStore('localChatStore', () => {
addText(msg)
}
if (msg.type === "image"){
console.log(msg)
}
if (msg.type === "fileSending"){
@ -403,123 +403,7 @@ export const useLocalChatStore = defineStore('localChatStore', () => {
await updateContentList(saveMsg)
}
//上传文件资源
// async function uploadFile(paths: any) {
// if (chatTargetId.value < 1) {
// return
// }
// const targetUser = userList.value.find((d: any) => d.ip === chatTargetIp.value)
// if (!targetUser.isOnline) {
// notifyError("The user is not online!");
// return;
// }
// if (!hostInfo.value || !hostInfo.value.ip) {
// notifyError("Please wait for a moment");
// return;
// }
// //console.log(paths)
// const formData = new FormData();
// const errstr: any = []
// const files: any = []
// for (let i = 0; i < paths.length; i++) {
// const content = await sys?.fs.readFile(paths[i]);
// let blobContent;
// if (!content || content == '') {
// errstr.push(paths[i] + " is empty")
// continue
// }
// if (content instanceof ArrayBuffer) {
// blobContent = new Blob([content]);
// }
// else if (typeof content === 'string') {
// if (isBase64(content)) {
// const base64 = base64ToBuffer(content);
// blobContent = new Blob([base64]);
// } else {
// blobContent = new Blob([content], { type: "text/plain;charset=utf-8" });
// }
// }
// else {
// errstr.push(paths[i] + " type is error")
// continue
// }
// const fileName = paths[i].split("/").pop()
// files.push({
// name: fileName,
// path: paths[i],
// ext: fileName.split(".").pop(),
// })
// //files.push(blobContent);
// formData.append(`files`, blobContent, fileName);
// }
// if (errstr.length > 0) {
// errstr.forEach((d: any) => {
// notifyError(d);
// })
// return
// }
// //formData.append("files", files);
// formData.append("ip", hostInfo.value.ip);
// formData.append("hostname", hostInfo.value.hostname);
// //console.log(formData)
// const postUrl = `http://${targetUser.ip}:56780/localchat/upload`
// const res = await fetch(postUrl, {
// method: "POST",
// body: formData,
// });
// if (!res.ok) {
// console.log(res);
// notifyError("Upload error!");
// return;
// }
// const saveMsg: any = {
// type: 'file',
// targetId: targetUser.id,
// targetIp: targetUser.ip,
// content: files,
// reciperInfo: toRaw(targetUser),
// createdAt: Date.now(),
// isMe: false,
// isRead: true,
// status: 'reciped'
// }
// //console.log(saveMsg)
// await db.addOne('chatmsg', saveMsg)
// msgList.value.push(saveMsg)
// notifySuccess("upload success!");
// }
//async function addUser(ip: string) {
// if (!isValidIP(ip)) {
// notifyError("请输入正确的IP地址");
// return
// }
// const postUrl = `http://${ip}:56780/localchat/check`
// const completion = await fetch(postUrl)
// if (!completion.ok) {
// notifyError('用户不在线')
// } else {
// const res = await completion.json()
// const data = res.data
// data.createdAt = Date.now()
// data.updatedAt = Date.now()
// data.isOnline = true
// data.username = data.hostname
// if(ip != data.ip){
// notifyError(`IP地址不一致,可能会存在不通的问题`)
// }
// data.ip = ip
// if (!OutUserList.value.some((item: any) => item.ip === data.ip)) {
// OutUserList.value.push(data);
// await getUserList()
// }
// showAddUser.value = false
// }
//}
return {
userList,
navList,

56
godo/localchat/file.go

@ -33,6 +33,7 @@ import (
"net/http"
"os"
"path/filepath"
"sync"
"time"
)
@ -46,6 +47,7 @@ type FileChunk struct {
Checksum uint32 `json:"checksum"`
Timestamp time.Time `json:"timestamp"`
Filename string `json:"filename"`
Filesize int64 `json:"filesize"`
}
func HandlerApplySendFile(w http.ResponseWriter, r *http.Request) {
@ -146,7 +148,7 @@ func handleFile(filePath string, toIp string, message UdpMessage) {
numChunks := (fileSize + fileSize - 1) / fileSize
// 发送文件
SendFile(file, int(numChunks), toIp, message)
SendFile(file, int(numChunks), toIp, fileSize, message)
}
func handleDirectory(dirPath string, toIp string, message UdpMessage) {
@ -163,9 +165,16 @@ func handleDirectory(dirPath string, toIp string, message UdpMessage) {
log.Fatalf("Failed to walk directory: %v", err)
}
}
func SendFile(file *os.File, numChunks int, toIp string, message UdpMessage) {
func SendFile(file *os.File, numChunks int, toIp string, fSize int64, message UdpMessage) {
var wg sync.WaitGroup
mu := &sync.Mutex{}
// 逐块读取文件并发送
for i := 0; i < numChunks; i++ {
wg.Add(1)
go func(index int) {
defer wg.Done()
var chunkData [fileSize]byte
n, err := file.Read(chunkData[:])
if err != nil && err != io.EOF {
@ -174,13 +183,15 @@ func SendFile(file *os.File, numChunks int, toIp string, message UdpMessage) {
// 创建文件块
chunk := FileChunk{
ChunkIndex: i,
ChunkIndex: index,
Data: chunkData[:n],
Checksum: calculateChecksum(chunkData[:n]),
Timestamp: time.Now(),
Filename: filepath.Base(file.Name()),
Filesize: fSize,
}
message.Message = chunk
// 将文件块转换为 JSON 格式
data, err := json.Marshal(message)
if err != nil {
@ -188,7 +199,6 @@ func SendFile(file *os.File, numChunks int, toIp string, message UdpMessage) {
}
// 发送文件块
//addr, err := net.ResolveUDPAddr("udp4", toIp+":56780")
port := "56780"
addr, err := net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%s", toIp, port))
if err != nil {
@ -206,32 +216,38 @@ func SendFile(file *os.File, numChunks int, toIp string, message UdpMessage) {
log.Printf("Failed to write data: %v", err)
}
fmt.Printf("发送文件块 %d 到 %s 成功\n", i, toIp)
mu.Lock()
fmt.Printf("发送文件块 %d 到 %s 成功\n", index, toIp)
mu.Unlock()
}(i)
}
wg.Wait()
}
func ReceiveFile(msg UdpMessage) {
func ReceiveFile(msg UdpMessage) (string, error) {
chunk := msg.Message.(FileChunk)
// 验证校验和
calculatedChecksum := calculateChecksum(chunk.Data)
if calculatedChecksum != chunk.Checksum {
fmt.Printf("Checksum mismatch for chunk %d from %s\n", chunk.ChunkIndex, msg.IP)
return
return "", fmt.Errorf("checksum mismatch")
}
baseDir, err := libs.GetOsDir()
if err != nil {
log.Printf("Failed to get OS directory: %v", err)
return
return "", fmt.Errorf("failed to get OS directory")
}
// 创建接收文件的目录
receiveDir := filepath.Join(baseDir, "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)
if !libs.PathExists(receiveDir) {
err := os.MkdirAll(receiveDir, 0755)
if err != nil {
log.Printf("Failed to create receive directory: %v", err)
return
return "", fmt.Errorf("failed to create receive directory")
}
}
@ -243,7 +259,7 @@ func ReceiveFile(msg UdpMessage) {
file, err := os.Create(filePath)
if err != nil {
log.Printf("Failed to create file: %v", err)
return
return "", fmt.Errorf("failed to create file")
}
defer file.Close()
}
@ -252,7 +268,7 @@ func ReceiveFile(msg UdpMessage) {
file, err := os.OpenFile(filePath, os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
log.Printf("Failed to open file: %v", err)
return
return "", fmt.Errorf("failed to open file")
}
defer file.Close()
@ -260,10 +276,20 @@ func ReceiveFile(msg UdpMessage) {
_, err = file.Write(chunk.Data)
if err != nil {
log.Printf("Failed to write data to file: %v", err)
return
return "", fmt.Errorf("failed to write data to file")
}
fileInfo, err := os.Stat(filePath)
if err != nil {
log.Printf("Failed to stat file: %v", err)
return "", fmt.Errorf("failed to stat file")
}
if fileInfo.Size() == chunk.Filesize {
fmt.Println("文件接收完成且大小一致")
return filePath, nil
} else {
fmt.Println("文件大小不一致")
return "", fmt.Errorf("file size mismatch")
}
fmt.Printf("接收到文件块 %d 从 %s 成功\n", chunk.ChunkIndex, msg.IP)
}
func calculateChecksum(data []byte) uint32 {
checksum := uint32(0)

184
godo/localchat/image.go

@ -26,11 +26,9 @@ package localchat
import (
"encoding/json"
"fmt"
"godo/libs"
"io"
"log"
"net"
"net/http"
"net/url"
"os"
@ -60,10 +58,10 @@ func HandlerSendImg(w http.ResponseWriter, r *http.Request) {
log.Printf("GetOsDir error: %v", err)
return
}
log.Printf("send image to %v", msg.Message)
log.Printf("Type of msg.Message: %T", msg.Message)
// log.Printf("send image to %v", msg.Message)
// log.Printf("Type of msg.Message: %T", msg.Message)
paths, ok := msg.Message.([]interface{})
log.Printf("paths: %v", paths)
//log.Printf("paths: %v", paths)
if !ok {
libs.ErrorMsg(w, "HandleMessage message error")
return
@ -78,7 +76,7 @@ func HandlerSendImg(w http.ResponseWriter, r *http.Request) {
// 处理多张图片
if fileInfo, err := os.Stat(filePath); err == nil {
if !fileInfo.IsDir() {
sendImage(filePath, toIp, msg)
handleFile(filePath, toIp, msg)
}
} else {
continue
@ -87,121 +85,65 @@ func HandlerSendImg(w http.ResponseWriter, r *http.Request) {
libs.SuccessMsg(w, nil, "图片发送成功")
}
func sendImage(filePath string, toIp string, message UdpMessage) {
// 打开文件
file, err := os.Open(filePath)
if err != nil {
log.Fatalf("Failed to open file: %v", err)
}
defer file.Close()
// 获取文件大小
fileInfo, err := file.Stat()
if err != nil {
log.Fatalf("Failed to get file info: %v", err)
}
fileSize := fileInfo.Size()
// 读取整个文件
data := make([]byte, fileSize)
_, err = file.Read(data)
if err != nil {
log.Fatalf("Failed to read file: %v", err)
}
// 创建文件块
chunk := FileChunk{
Data: data,
Checksum: calculateChecksum(data),
Timestamp: time.Now(),
Filename: filepath.Base(file.Name()),
}
message.Message = chunk
// 将文件块转换为 JSON 格式
data, err = json.Marshal(message)
if err != nil {
log.Fatalf("Failed to marshal chunk: %v", err)
}
// 发送文件块
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()
_, err = conn.Write(data)
if err != nil {
log.Printf("Failed to write data: %v", err)
}
fmt.Printf("发送图片 %s 到 %s 成功\n", filePath, toIp)
}
func ReceiveImg(msg UdpMessage) (string, error) {
chunk := msg.Message.(FileChunk)
// 验证校验和
calculatedChecksum := calculateChecksum(chunk.Data)
if calculatedChecksum != chunk.Checksum {
fmt.Printf("Checksum mismatch for image from %s\n", msg.IP)
return "", fmt.Errorf("checksum mismatch")
}
baseDir, err := libs.GetOsDir()
if err != nil {
log.Printf("Failed to get OS directory: %v", err)
return "", err
}
// 创建接收文件的目录
resPath := filepath.Join("C", "Users", "Reciv", time.Now().Format("2006-01-02"))
receiveDir := filepath.Join(baseDir, resPath)
if !libs.PathExists(receiveDir) {
err := os.MkdirAll(receiveDir, 0755)
if err != nil {
log.Printf("Failed to create receive directory: %v", err)
return "", err
}
}
// 确定文件路径
filePath := filepath.Join(receiveDir, chunk.Filename)
// 如果文件不存在,则创建新文件
if _, err := os.Stat(filePath); os.IsNotExist(err) {
file, err := os.Create(filePath)
if err != nil {
log.Printf("Failed to create file: %v", err)
return "", err
}
defer file.Close()
}
// 打开或追加到现有文件
file, err := os.OpenFile(filePath, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Printf("Failed to open file: %v", err)
return "", err
}
defer file.Close()
// 写入数据
_, err = file.Write(chunk.Data)
if err != nil {
log.Printf("Failed to write data to file: %v", err)
return "", err
}
fmt.Printf("接收到图片 %s 从 %s 成功\n", filePath, msg.IP)
resFilePath := filepath.Join(resPath, chunk.Filename)
return resFilePath, nil
}
// func ReceiveImg(msg UdpMessage) (string, error) {
// chunk := msg.Message.(FileChunk)
// // 验证校验和
// calculatedChecksum := calculateChecksum(chunk.Data)
// if calculatedChecksum != chunk.Checksum {
// fmt.Printf("Checksum mismatch for image from %s\n", msg.IP)
// return "", fmt.Errorf("checksum mismatch")
// }
// baseDir, err := libs.GetOsDir()
// if err != nil {
// log.Printf("Failed to get OS directory: %v", err)
// return "", err
// }
// // 创建接收文件的目录
// resPath := filepath.Join("C", "Users", "Reciv", time.Now().Format("2006-01-02"))
// receiveDir := filepath.Join(baseDir, resPath)
// if !libs.PathExists(receiveDir) {
// err := os.MkdirAll(receiveDir, 0755)
// if err != nil {
// log.Printf("Failed to create receive directory: %v", err)
// return "", err
// }
// }
// // 确定文件路径
// filePath := filepath.Join(receiveDir, chunk.Filename)
// // 如果文件不存在,则创建新文件
// if _, err := os.Stat(filePath); os.IsNotExist(err) {
// file, err := os.Create(filePath)
// if err != nil {
// log.Printf("Failed to create file: %v", err)
// return "", err
// }
// defer file.Close()
// }
// // 打开或追加到现有文件
// file, err := os.OpenFile(filePath, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644)
// if err != nil {
// log.Printf("Failed to open file: %v", err)
// return "", err
// }
// defer file.Close()
// // 写入数据
// _, err = file.Write(chunk.Data)
// if err != nil {
// log.Printf("Failed to write data to file: %v", err)
// return "", err
// }
// fmt.Printf("接收到图片 %s 从 %s 成功\n", filePath, msg.IP)
// resFilePath := filepath.Join(resPath, chunk.Filename)
// return resFilePath, nil
// }
func HandleViewImg(w http.ResponseWriter, r *http.Request) {
img := r.URL.Query().Get("img")
if img == "" {

2
godo/localchat/server.go

@ -118,7 +118,7 @@ func UdpServer() {
continue
}
if udpMsg.Type == "image" {
filePath, err := ReceiveImg(udpMsg)
filePath, err := ReceiveFile(udpMsg)
if err != nil {
log.Printf("error receiving image: %v", err)
continue

Loading…
Cancel
Save