feat: implement ListFiles and DownloadFile RPCs with documentation updates in GRPC.md
This commit is contained in:
@@ -7,16 +7,30 @@ import (
|
||||
"io"
|
||||
"math/rand"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/reflection"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
var min = 0
|
||||
var max = 100
|
||||
var port = ":8080"
|
||||
|
||||
type UploadedFile struct {
|
||||
FileName string
|
||||
Content []byte
|
||||
UploadedAt int64
|
||||
}
|
||||
|
||||
var (
|
||||
fileStore = make(map[string]*UploadedFile)
|
||||
storeMu sync.RWMutex
|
||||
)
|
||||
|
||||
func random(min, max int, src rand.Source) int {
|
||||
return rand.New(src).Intn(max-min) + min
|
||||
}
|
||||
@@ -89,11 +103,23 @@ func (IoTServer) GetRandomPass(ctx context.Context, r *protoapi.RequestPass) (*p
|
||||
func (IoTServer) UploadFile(stream protoapi.IoTService_UploadFileServer) error {
|
||||
var totalBytes int64
|
||||
var fileName string
|
||||
var buffer []byte
|
||||
|
||||
for {
|
||||
chunk, err := stream.Recv()
|
||||
if err == io.EOF {
|
||||
fmt.Printf("File upload completed. Received %d bytes for file '%s'\n", totalBytes, fileName)
|
||||
|
||||
if fileName != "" {
|
||||
storeMu.Lock()
|
||||
fileStore[fileName] = &UploadedFile{
|
||||
FileName: fileName,
|
||||
Content: buffer,
|
||||
UploadedAt: time.Now().Unix(),
|
||||
}
|
||||
storeMu.Unlock()
|
||||
}
|
||||
|
||||
return stream.SendAndClose(&protoapi.UploadStatus{
|
||||
Success: true,
|
||||
Message: fmt.Sprintf("File '%s' uploaded successfully.", fileName),
|
||||
@@ -108,10 +134,57 @@ func (IoTServer) UploadFile(stream protoapi.IoTService_UploadFileServer) error {
|
||||
if fileName == "" {
|
||||
fileName = chunk.GetFileName()
|
||||
}
|
||||
buffer = append(buffer, chunk.GetContent()...)
|
||||
totalBytes += int64(len(chunk.GetContent()))
|
||||
}
|
||||
}
|
||||
|
||||
func (IoTServer) ListFiles(ctx context.Context, r *protoapi.EmptyRequest) (*protoapi.FileList, error) {
|
||||
storeMu.RLock()
|
||||
defer storeMu.RUnlock()
|
||||
|
||||
var files []*protoapi.FileMetadata
|
||||
for _, f := range fileStore {
|
||||
files = append(files, &protoapi.FileMetadata{
|
||||
FileName: f.FileName,
|
||||
FileSize: int64(len(f.Content)),
|
||||
UploadedAt: f.UploadedAt,
|
||||
})
|
||||
}
|
||||
|
||||
return &protoapi.FileList{Files: files}, nil
|
||||
}
|
||||
|
||||
func (IoTServer) DownloadFile(r *protoapi.DownloadRequest, stream protoapi.IoTService_DownloadFileServer) error {
|
||||
storeMu.RLock()
|
||||
f, exists := fileStore[r.GetFileName()]
|
||||
storeMu.RUnlock()
|
||||
|
||||
if !exists {
|
||||
return status.Errorf(codes.NotFound, "file %s not found", r.GetFileName())
|
||||
}
|
||||
|
||||
chunkSize := 1024 // 1KB 청크 단위
|
||||
totalBytes := len(f.Content)
|
||||
|
||||
for i := 0; i < totalBytes; i += chunkSize {
|
||||
end := i + chunkSize
|
||||
if end > totalBytes {
|
||||
end = totalBytes
|
||||
}
|
||||
|
||||
err := stream.Send(&protoapi.FileChunk{
|
||||
FileName: f.FileName,
|
||||
Content: f.Content[i:end],
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ServerRun(addr string) {
|
||||
server := grpc.NewServer()
|
||||
var iotServer IoTServer
|
||||
|
||||
Reference in New Issue
Block a user