Files
2026-05-21 19:52:45 +08:00

158 lines
4.5 KiB
Go

package share
import (
"fmt"
"net/http"
"net/url"
"github.com/labstack/echo/v4"
v1 "github.com/chaitin/panda-wiki/api/share/v1"
"github.com/chaitin/panda-wiki/handler"
"github.com/chaitin/panda-wiki/log"
"github.com/chaitin/panda-wiki/usecase"
"github.com/chaitin/panda-wiki/utils"
)
type ShareCommonHandler struct {
*handler.BaseHandler
logger *log.Logger
fileUsecase *usecase.FileUsecase
}
func NewShareCommonHandler(
e *echo.Echo,
baseHandler *handler.BaseHandler,
logger *log.Logger,
fileUsecase *usecase.FileUsecase,
) *ShareCommonHandler {
h := &ShareCommonHandler{
BaseHandler: baseHandler,
logger: logger,
fileUsecase: fileUsecase,
}
share := e.Group("share/v1/common",
func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
c.Response().Header().Set("Access-Control-Allow-Origin", "*")
c.Response().Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
c.Response().Header().Set("Access-Control-Allow-Headers", "Content-Type, Origin, Accept")
if c.Request().Method == "OPTIONS" {
return c.NoContent(http.StatusOK)
}
return next(c)
}
})
share.POST("/file/upload", h.FileUpload, h.ShareAuthMiddleware.Authorize)
share.POST("/file/upload/url", h.FileUploadByUrl, h.ShareAuthMiddleware.Authorize)
return h
}
// FileUpload 文件上传
//
// @Tags ShareFile
// @Summary 文件上传
// @Description 前台用户上传文件,目前只支持图片文件上传
// @ID share-FileUpload
// @Accept multipart/form-data
// @Produce json
// @Param X-KB-ID header string true "kb id"
// @Param file formData file true "File"
// @Param captcha_token formData string true "captcha_token"
// @Success 200 {object} domain.Response{data=v1.FileUploadResp}
// @Router /share/v1/common/file/upload [post]
func (h *ShareCommonHandler) FileUpload(c echo.Context) error {
ctx := c.Request().Context()
var req v1.ShareFileUploadReq
if err := c.Bind(&req); err != nil {
return h.NewResponseWithError(c, "invalid request parameters", err)
}
if err := c.Validate(req); err != nil {
return h.NewResponseWithError(c, "validate request body failed", err)
}
kbID := c.Request().Header.Get("X-KB-ID")
if kbID == "" {
return h.NewResponseWithError(c, "kb_id is required", nil)
}
req.KbId = kbID
file, err := c.FormFile("file")
if err != nil {
return h.NewResponseWithError(c, "failed to get file", err)
}
if !utils.IsImageFile(file.Filename) {
return h.NewResponseWithError(c, "只支持图片文件上传", fmt.Errorf("unsupported file type: %s", file.Filename))
}
// validate captcha token
if !h.Captcha.ValidateToken(ctx, req.CaptchaToken) {
return h.NewResponseWithError(c, "failed to validate captcha token", nil)
}
key, err := h.fileUsecase.UploadFile(ctx, req.KbId, file)
if err != nil {
return h.NewResponseWithError(c, "upload failed", err)
}
return h.NewResponseWithData(c, v1.FileUploadResp{
Key: key,
})
}
// FileUploadByUrl 通过url上传文件
//
// @Tags ShareFile
// @Summary 文件上传
// @Description 前台用户上传文件,目前只支持图片文件上传
// @ID share-FileUploadByUrl
// @Accept json
// @Produce json
// @Param body body v1.ShareFileUploadUrlReq true "body"
// @Success 200 {object} domain.Response{data=v1.ShareFileUploadUrlResp}
// @Router /share/v1/common/file/upload/url [post]
func (h *ShareCommonHandler) FileUploadByUrl(c echo.Context) error {
ctx := c.Request().Context()
var req v1.ShareFileUploadUrlReq
if err := c.Bind(&req); err != nil {
return h.NewResponseWithError(c, "invalid request parameters", err)
}
if err := c.Validate(req); err != nil {
return h.NewResponseWithError(c, "validate request body failed", err)
}
kbID := c.Request().Header.Get("X-KB-ID")
if kbID == "" {
return h.NewResponseWithError(c, "kb_id is required", nil)
}
req.KbId = kbID
parsedURL, err := url.Parse(req.Url)
if err != nil {
return h.NewResponseWithError(c, "invalid URL format", err)
}
if !utils.IsImageFile(parsedURL.Path) {
return h.NewResponseWithError(c, "只支持图片文件上传", fmt.Errorf("unsupported file type: %s", req.Url))
}
// validate captcha token
if !h.Captcha.ValidateToken(ctx, req.CaptchaToken) {
return h.NewResponseWithError(c, "failed to validate captcha token", nil)
}
key, err := h.fileUsecase.UploadFileByUrl(ctx, req.KbId, req.Url)
if err != nil {
return h.NewResponseWithError(c, "upload failed", err)
}
return h.NewResponseWithData(c, v1.ShareFileUploadUrlResp{
Key: key,
})
}