Add UploadHandler (5 endpoints), FileHandler (4 endpoints), FolderHandler (4 endpoints) with Gin route registration in server.go. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
139 lines
3.6 KiB
Go
139 lines
3.6 KiB
Go
package handler
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"strconv"
|
|
|
|
"gcy_hpc_server/internal/model"
|
|
"gcy_hpc_server/internal/server"
|
|
"gcy_hpc_server/internal/service"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type fileServiceProvider interface {
|
|
ListFiles(ctx context.Context, folderID *int64, page, pageSize int, search string) ([]model.FileResponse, int64, error)
|
|
GetFileMetadata(ctx context.Context, fileID int64) (*model.File, *model.FileBlob, error)
|
|
DownloadFile(ctx context.Context, fileID int64, rangeHeader string) (io.ReadCloser, *model.File, *model.FileBlob, int64, int64, error)
|
|
DeleteFile(ctx context.Context, fileID int64) error
|
|
}
|
|
|
|
type FileHandler struct {
|
|
svc fileServiceProvider
|
|
logger *zap.Logger
|
|
}
|
|
|
|
func NewFileHandler(svc *service.FileService, logger *zap.Logger) *FileHandler {
|
|
return &FileHandler{svc: svc, logger: logger}
|
|
}
|
|
|
|
func (h *FileHandler) ListFiles(c *gin.Context) {
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
|
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
if pageSize < 1 {
|
|
pageSize = 10
|
|
}
|
|
|
|
var folderID *int64
|
|
if v := c.Query("folder_id"); v != "" {
|
|
id, err := strconv.ParseInt(v, 10, 64)
|
|
if err != nil {
|
|
h.logger.Warn("invalid folder_id", zap.String("folder_id", v))
|
|
server.BadRequest(c, "invalid folder_id")
|
|
return
|
|
}
|
|
folderID = &id
|
|
}
|
|
|
|
search := c.Query("search")
|
|
|
|
files, total, err := h.svc.ListFiles(c.Request.Context(), folderID, page, pageSize, search)
|
|
if err != nil {
|
|
h.logger.Error("failed to list files", zap.Error(err))
|
|
server.InternalError(c, err.Error())
|
|
return
|
|
}
|
|
|
|
server.OK(c, model.ListFilesResponse{
|
|
Files: files,
|
|
Total: total,
|
|
Page: page,
|
|
PageSize: pageSize,
|
|
})
|
|
}
|
|
|
|
func (h *FileHandler) GetFile(c *gin.Context) {
|
|
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
h.logger.Warn("invalid file id", zap.String("id", c.Param("id")))
|
|
server.BadRequest(c, "invalid id")
|
|
return
|
|
}
|
|
|
|
file, blob, err := h.svc.GetFileMetadata(c.Request.Context(), id)
|
|
if err != nil {
|
|
h.logger.Error("failed to get file", zap.Int64("id", id), zap.Error(err))
|
|
server.InternalError(c, err.Error())
|
|
return
|
|
}
|
|
|
|
resp := model.FileResponse{
|
|
ID: file.ID,
|
|
Name: file.Name,
|
|
FolderID: file.FolderID,
|
|
Size: blob.FileSize,
|
|
MimeType: blob.MimeType,
|
|
SHA256: file.BlobSHA256,
|
|
CreatedAt: file.CreatedAt,
|
|
UpdatedAt: file.UpdatedAt,
|
|
}
|
|
server.OK(c, resp)
|
|
}
|
|
|
|
func (h *FileHandler) DownloadFile(c *gin.Context) {
|
|
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
h.logger.Warn("invalid file id for download", zap.String("id", c.Param("id")))
|
|
server.BadRequest(c, "invalid id")
|
|
return
|
|
}
|
|
|
|
rangeHeader := c.GetHeader("Range")
|
|
|
|
reader, file, blob, start, end, err := h.svc.DownloadFile(c.Request.Context(), id, rangeHeader)
|
|
if err != nil {
|
|
h.logger.Error("failed to download file", zap.Int64("id", id), zap.Error(err))
|
|
server.InternalError(c, err.Error())
|
|
return
|
|
}
|
|
|
|
if rangeHeader != "" {
|
|
server.StreamRange(c, reader, start, end, blob.FileSize, blob.MimeType)
|
|
} else {
|
|
server.StreamFile(c, reader, file.Name, blob.FileSize, blob.MimeType)
|
|
}
|
|
}
|
|
|
|
func (h *FileHandler) DeleteFile(c *gin.Context) {
|
|
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
h.logger.Warn("invalid file id for delete", zap.String("id", c.Param("id")))
|
|
server.BadRequest(c, "invalid id")
|
|
return
|
|
}
|
|
|
|
if err := h.svc.DeleteFile(c.Request.Context(), id); err != nil {
|
|
h.logger.Error("failed to delete file", zap.Int64("id", id), zap.Error(err))
|
|
server.InternalError(c, err.Error())
|
|
return
|
|
}
|
|
|
|
h.logger.Info("file deleted", zap.Int64("id", id))
|
|
server.OK(c, gin.H{"message": "file deleted"})
|
|
}
|