การดู : 0
04/03/2026 08:51น.

EP.40 การเพิ่มฟีเจอร์อัปโหลดไฟล์ใน WebSocket Chat
#Chat Media Upload
#Firebase Storage
#AWS S3
#GraphQL File Upload
#WebSocket File Sharing
#Real-Time Chat
#Golang
#Go
#WebSocket
#File Upload
ทำไมต้องมีฟีเจอร์อัปโหลดไฟล์ใน WebSocket Chat?
ในระบบแชทที่ทันสมัย ผู้ใช้ต้องการสามารถ แชร์ไฟล์ รูปภาพ และเอกสาร ระหว่างกันได้ การเพิ่มฟีเจอร์ อัปโหลดไฟล์ผ่าน WebSocket ทำให้ผู้ใช้สามารถส่งไฟล์ได้แบบเรียลไทม์โดยไม่ต้องโหลดหน้าใหม่ ซึ่งเหมาะสำหรับ:
- ระบบแชทภายในองค์กร ที่ต้องแชร์เอกสารและไฟล์งาน
- แพลตฟอร์มโซเชียลมีเดีย ที่ให้ผู้ใช้ส่งรูปภาพและวิดีโอ
- บริการสนับสนุนลูกค้า ที่ต้องส่งไฟล์แนบหรือภาพถ่ายปัญหาต่างๆ
โครงสร้างของระบบอัปโหลดไฟล์ใน WebSocket Chat
- WebSocket Server - รับไฟล์จากผู้ใช้และกระจายไปยังผู้ใช้ที่เกี่ยวข้อง
- GraphQL API - ใช้เพื่อจัดการการอัปโหลดไฟล์และเก็บเมตะดาต้า
- File Storage - จัดเก็บไฟล์ในเซิร์ฟเวอร์หรือ Cloud Storage (เช่น AWS S3 หรือ Firebase Storage)
- Database (PostgreSQL / MongoDB) - เก็บข้อมูลไฟล์ เช่น URL และข้อมูลผู้ส่ง
ติดตั้งไลบรารีที่จำเป็น
go get github.com/gorilla/websocket
go get github.com/minio/minio-go/v7การตั้งค่าฐานข้อมูลสำหรับเก็บข้อมูลไฟล์
ไฟล์ schema.sql
CREATE TABLE chat_files (
id SERIAL PRIMARY KEY,
room_id INTEGER NOT NULL,
sender TEXT NOT NULL,
file_url TEXT NOT NULL,
file_name TEXT NOT NULL,
file_type TEXT NOT NULL,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);การสร้าง GraphQL Schema สำหรับการอัปโหลดไฟล์
ไฟล์ schema.graphql
type Mutation {
uploadFile(roomID: ID!, sender: String!, fileName: String!, fileType: String!, fileContent: String!): ChatFile!
}
type ChatFile {
id: ID!
roomID: ID!
sender: String!
fileURL: String!
fileName: String!
fileType: String!
timestamp: String!
}การสร้าง Resolver สำหรับการอัปโหลดไฟล์
ไฟล์ resolver.go
package main
import (
"context"
"encoding/base64"
"fmt"
"os"
"path/filepath"
"time"
)
type ChatFile struct {
ID int `json:"id"`
RoomID int `json:"roomID"`
Sender string `json:"sender"`
FileURL string `json:"fileURL"`
FileName string `json:"fileName"`
FileType string `json:"fileType"`
Timestamp time.Time `json:"timestamp"`
}
func (r *Resolver) Mutation_uploadFile(ctx context.Context, roomID int, sender string, fileName string, fileType string, fileContent string) (ChatFile, error) {
decoded, err := base64.StdEncoding.DecodeString(fileContent)
if err != nil {
return ChatFile{}, err
}
savePath := filepath.Join("uploads", fileName)
err = os.WriteFile(savePath, decoded, 0644)
if err != nil {
return ChatFile{}, err
}
fileURL := fmt.Sprintf("/uploads/%s", fileName)
file := ChatFile{RoomID: roomID, Sender: sender, FileURL: fileURL, FileName: fileName, FileType: fileType, Timestamp: time.Now()}
return file, nil
}การส่งไฟล์ผ่าน WebSocket
ไฟล์ websocket_server.go
package main
import (
"encoding/json"
"fmt"
"net/http"
"github.com/gorilla/websocket"
)
type FileMessage struct {
RoomID int `json:"roomID"`
Sender string `json:"sender"`
FileName string `json:"fileName"`
FileType string `json:"fileType"`
FileURL string `json:"fileURL"`
}
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true },
}
func handleWebSocket(w http.ResponseWriter, r *http.Request) {
conn, _ := upgrader.Upgrade(w, r, nil)
defer conn.Close()
fmt.Println("Client connected")
for {
_, msg, err := conn.ReadMessage()
if err != nil {
break
}
var fileMsg FileMessage
json.Unmarshal(msg, &fileMsg)
fmt.Printf("Received file: %s from %s\n", fileMsg.FileName, fileMsg.Sender)
}
}
func main() {
http.HandleFunc("/ws", handleWebSocket)
fmt.Println("WebSocket Server Running on Port 8080")
http.ListenAndServe(":8080", nil)
}การอัปโหลดไฟล์จากฝั่ง Client
ไฟล์ client.js
async function uploadFile(file) {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = async () => {
const base64Content = reader.result.split(",")[1];
const response = await fetch("/graphql", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
query: `mutation { uploadFile(roomID: 1, sender: "JohnDoe", fileName: "${file.name}", fileType: "${file.type}", fileContent: "${base64Content}" ) { fileURL } }`
})
});
console.log(await response.json());
};
}ท้าให้ลอง!
ลองเพิ่ม ระบบแสดงตัวอย่างไฟล์ก่อนอัปโหลด เพื่อให้ผู้ใช้สามารถดูไฟล์ก่อนกดส่งไปยังห้องแชท
EP ถัดไป
ใน EP.41, เราจะเพิ่ม ฟีเจอร์แสดงสถานะการพิมพ์ (Typing Indicator) ใน WebSocket Chat 🚀