meti-backend/internal/handler/file_handler.go

79 lines
2.7 KiB
Go
Raw Normal View History

2025-08-09 15:08:26 +07:00
package handler
import (
"context"
"io"
"net/http"
"eslogad-be/internal/appcontext"
"eslogad-be/internal/contract"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
)
type FileService interface {
UploadProfileAvatar(ctx context.Context, userID uuid.UUID, filename string, content []byte, contentType string) (string, error)
UploadDocument(ctx context.Context, userID uuid.UUID, filename string, content []byte, contentType string) (string, string, error)
}
type FileHandler struct {
service FileService
}
func NewFileHandler(service FileService) *FileHandler {
return &FileHandler{service: service}
}
func (h *FileHandler) UploadProfileAvatar(c *gin.Context) {
appCtx := appcontext.FromGinContext(c.Request.Context())
if appCtx.UserID == uuid.Nil {
c.JSON(http.StatusUnauthorized, &contract.ErrorResponse{Error: "Unauthorized", Code: http.StatusUnauthorized})
return
}
file, header, err := c.Request.FormFile("file")
if err != nil {
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "file is required", Code: http.StatusBadRequest})
return
}
defer file.Close()
content, err := io.ReadAll(io.LimitReader(file, 10<<20))
if err != nil {
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "failed to read file", Code: http.StatusBadRequest})
return
}
ct := header.Header.Get("Content-Type")
url, err := h.service.UploadProfileAvatar(c.Request.Context(), appCtx.UserID, header.Filename, content, ct)
if err != nil {
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
return
}
c.JSON(http.StatusOK, contract.BuildSuccessResponse(map[string]string{"url": url}))
}
func (h *FileHandler) UploadDocument(c *gin.Context) {
appCtx := appcontext.FromGinContext(c.Request.Context())
if appCtx.UserID == uuid.Nil {
c.JSON(http.StatusUnauthorized, &contract.ErrorResponse{Error: "Unauthorized", Code: http.StatusUnauthorized})
return
}
file, header, err := c.Request.FormFile("file")
if err != nil {
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "file is required", Code: http.StatusBadRequest})
return
}
defer file.Close()
content, err := io.ReadAll(io.LimitReader(file, 20<<20))
if err != nil {
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "failed to read file", Code: http.StatusBadRequest})
return
}
ct := header.Header.Get("Content-Type")
url, key, err := h.service.UploadDocument(c.Request.Context(), appCtx.UserID, header.Filename, content, ct)
if err != nil {
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
return
}
c.JSON(http.StatusOK, contract.BuildSuccessResponse(map[string]string{"url": url, "key": key}))
}