feat: update oss download url

This commit is contained in:
2025-12-18 15:14:42 +08:00
parent 8a6da5b627
commit 5a1983f08b
14 changed files with 83 additions and 80 deletions

2
.gitignore vendored
View File

@@ -6,3 +6,5 @@
/upload /upload
texpixel texpixel
/vendor /vendor
dev_deploy.sh

View File

@@ -5,15 +5,46 @@ import (
"gitea.com/bitwsd/document_ai/api/v1/oss" "gitea.com/bitwsd/document_ai/api/v1/oss"
"gitea.com/bitwsd/document_ai/api/v1/task" "gitea.com/bitwsd/document_ai/api/v1/task"
"gitea.com/bitwsd/document_ai/api/v1/user" "gitea.com/bitwsd/document_ai/api/v1/user"
"gitea.com/bitwsd/document_ai/pkg/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
func SetupRouter(engine *gin.RouterGroup) { func SetupRouter(engine *gin.RouterGroup) {
v1 := engine.Group("/v1") v1 := engine.Group("/v1")
{ {
formula.SetupRouter(v1) formulaRouter := v1.Group("/formula", common.GetAuthMiddleware())
oss.SetupRouter(v1) {
task.SetupRouter(v1) endpoint := formula.NewFormulaEndpoint()
user.SetupRouter(v1) formulaRouter.POST("/recognition", endpoint.CreateTask)
formulaRouter.POST("/ai_enhance", endpoint.AIEnhanceRecognition)
formulaRouter.GET("/recognition/:task_no", endpoint.GetTaskStatus)
}
taskRouter := v1.Group("/task", common.GetAuthMiddleware())
{
endpoint := task.NewTaskEndpoint()
taskRouter.POST("/evaluate", endpoint.EvaluateTask)
taskRouter.GET("/list", endpoint.GetTaskList)
}
ossRouter := v1.Group("/oss", common.GetAuthMiddleware())
{
endpoint := oss.NewOSSEndpoint()
ossRouter.POST("/signature", endpoint.GetPostObjectSignature)
ossRouter.POST("/signature_url", endpoint.GetSignatureURL)
ossRouter.POST("/file/upload", endpoint.UploadFile)
}
userRouter := v1.Group("/user", common.GetAuthMiddleware())
{
userEndpoint := user.NewUserEndpoint()
{
userRouter.POST("/sms", userEndpoint.SendVerificationCode)
userRouter.POST("/register", userEndpoint.RegisterByEmail)
userRouter.POST("/login", userEndpoint.LoginByEmail)
userRouter.GET("/info", common.MustAuthMiddleware(), userEndpoint.GetUserInfo)
} }
} }
}
}

View File

@@ -1,16 +0,0 @@
package formula
import (
"gitea.com/bitwsd/document_ai/pkg/common"
"github.com/gin-gonic/gin"
)
func SetupRouter(engine *gin.RouterGroup) {
endpoint := NewFormulaEndpoint()
formulaRouter := engine.Group("/formula", common.GetAuthMiddleware())
{
formulaRouter.POST("/recognition", endpoint.CreateTask)
formulaRouter.POST("/ai_enhance", endpoint.AIEnhanceRecognition)
formulaRouter.GET("/recognition/:task_no", endpoint.GetTaskStatus)
}
}

View File

@@ -17,7 +17,14 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
) )
func GetPostObjectSignature(ctx *gin.Context) { type OSSEndpoint struct {
}
func NewOSSEndpoint() *OSSEndpoint {
return &OSSEndpoint{}
}
func (h *OSSEndpoint) GetPostObjectSignature(ctx *gin.Context) {
policyToken, err := oss.GetPolicyToken() policyToken, err := oss.GetPolicyToken()
if err != nil { if err != nil {
ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeSystemError, err.Error())) ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeSystemError, err.Error()))
@@ -36,7 +43,7 @@ func GetPostObjectSignature(ctx *gin.Context) {
// @Success 200 {object} common.Response{data=map[string]string{"sign_url":string, "repeat":bool, "path":string}} "Signed URL generated successfully" // @Success 200 {object} common.Response{data=map[string]string{"sign_url":string, "repeat":bool, "path":string}} "Signed URL generated successfully"
// @Failure 200 {object} common.Response "Error response" // @Failure 200 {object} common.Response "Error response"
// @Router /signature_url [get] // @Router /signature_url [get]
func GetSignatureURL(ctx *gin.Context) { func (h *OSSEndpoint) GetSignatureURL(ctx *gin.Context) {
type Req struct { type Req struct {
FileHash string `json:"file_hash" binding:"required"` FileHash string `json:"file_hash" binding:"required"`
FileName string `json:"file_name" binding:"required"` FileName string `json:"file_name" binding:"required"`
@@ -76,7 +83,7 @@ func GetSignatureURL(ctx *gin.Context) {
ctx.JSON(http.StatusOK, common.SuccessResponse(ctx, gin.H{"sign_url": url, "repeat": false, "path": path})) ctx.JSON(http.StatusOK, common.SuccessResponse(ctx, gin.H{"sign_url": url, "repeat": false, "path": path}))
} }
func UploadFile(ctx *gin.Context) { func (h *OSSEndpoint) UploadFile(ctx *gin.Context) {
if err := os.MkdirAll(config.GlobalConfig.UploadDir, 0755); err != nil { if err := os.MkdirAll(config.GlobalConfig.UploadDir, 0755); err != nil {
ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeSystemError, "Failed to create upload directory")) ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeSystemError, "Failed to create upload directory"))
return return

View File

@@ -1,12 +0,0 @@
package oss
import "github.com/gin-gonic/gin"
func SetupRouter(parent *gin.RouterGroup) {
router := parent.Group("oss")
{
router.POST("/signature", GetPostObjectSignature)
router.POST("/signature_url", GetSignatureURL)
router.POST("/file/upload", UploadFile)
}
}

View File

@@ -1,12 +0,0 @@
package task
import (
"gitea.com/bitwsd/document_ai/pkg/common"
"github.com/gin-gonic/gin"
)
func SetupRouter(engine *gin.RouterGroup) {
endpoint := NewTaskEndpoint()
engine.POST("/task/evaluate", endpoint.EvaluateTask)
engine.GET("/task/list", common.MustAuthMiddleware(), endpoint.GetTaskList)
}

View File

@@ -1,17 +0,0 @@
package user
import (
"gitea.com/bitwsd/document_ai/pkg/common"
"github.com/gin-gonic/gin"
)
func SetupRouter(router *gin.RouterGroup) {
userEndpoint := NewUserEndpoint()
userRouter := router.Group("/user")
{
userRouter.POST("/sms", userEndpoint.SendVerificationCode)
userRouter.POST("/register", userEndpoint.RegisterByEmail)
userRouter.POST("/login", userEndpoint.LoginByEmail)
userRouter.GET("/info", common.MustAuthMiddleware(), userEndpoint.GetUserInfo)
}
}

View File

@@ -39,7 +39,7 @@ aliyun:
template_code: "SMS_291510729" template_code: "SMS_291510729"
oss: oss:
endpoint: oss-cn-beijing.aliyuncs.com endpoint: static.texpixel.com
inner_endpoint: oss-cn-beijing-internal.aliyuncs.com inner_endpoint: oss-cn-beijing-internal.aliyuncs.com
access_key_id: LTAI5t8qXhow6NCdYDtu1saF access_key_id: LTAI5t8qXhow6NCdYDtu1saF
access_key_secret: qZ2SwYsNCEBckCVSOszH31yYwXU44A access_key_secret: qZ2SwYsNCEBckCVSOszH31yYwXU44A

View File

@@ -38,7 +38,7 @@ aliyun:
template_code: "SMS_291510729" template_code: "SMS_291510729"
oss: oss:
endpoint: oss-cn-beijing.aliyuncs.com endpoint: static.texpixel.com
inner_endpoint: oss-cn-beijing-internal.aliyuncs.com inner_endpoint: oss-cn-beijing-internal.aliyuncs.com
access_key_id: LTAI5t8qXhow6NCdYDtu1saF access_key_id: LTAI5t8qXhow6NCdYDtu1saF
access_key_secret: qZ2SwYsNCEBckCVSOszH31yYwXU44A access_key_secret: qZ2SwYsNCEBckCVSOszH31yYwXU44A

View File

@@ -17,8 +17,8 @@ type TaskListRequest struct {
type TaskListDTO struct { type TaskListDTO struct {
TaskID string `json:"task_id"` TaskID string `json:"task_id"`
FileName string `json:"file_name"` FileName string `json:"file_name"`
Status string `json:"status"` Status int `json:"status"`
Path string `json:"path"` OriginURL string `json:"origin_url"`
TaskType string `json:"task_type"` TaskType string `json:"task_type"`
CreatedAt string `json:"created_at"` CreatedAt string `json:"created_at"`
Latex string `json:"latex"` Latex string `json:"latex"`

View File

@@ -9,6 +9,7 @@ import (
"gitea.com/bitwsd/document_ai/internal/model/task" "gitea.com/bitwsd/document_ai/internal/model/task"
"gitea.com/bitwsd/document_ai/internal/storage/dao" "gitea.com/bitwsd/document_ai/internal/storage/dao"
"gitea.com/bitwsd/document_ai/pkg/log" "gitea.com/bitwsd/document_ai/pkg/log"
"gitea.com/bitwsd/document_ai/pkg/oss"
) )
type TaskService struct { type TaskService struct {
@@ -91,13 +92,17 @@ func (svc *TaskService) GetTaskList(ctx context.Context, req *task.TaskListReque
latex = recognitionResult.NewContentCodec().GetContent().(string) latex = recognitionResult.NewContentCodec().GetContent().(string)
markdown = fmt.Sprintf("$$%s$$", latex) markdown = fmt.Sprintf("$$%s$$", latex)
} }
originURL, err := oss.GetDownloadURL(ctx, item.FileURL)
if err != nil {
log.Error(ctx, "func", "GetTaskList", "msg", "get origin url failed", "error", err)
}
resp.TaskList = append(resp.TaskList, &task.TaskListDTO{ resp.TaskList = append(resp.TaskList, &task.TaskListDTO{
Latex: latex, Latex: latex,
Markdown: markdown, Markdown: markdown,
TaskID: item.TaskUUID, TaskID: item.TaskUUID,
FileName: item.FileName, FileName: item.FileName,
Status: item.Status.String(), Status: int(item.Status),
Path: item.FileURL, OriginURL: originURL,
TaskType: item.TaskType.String(), TaskType: item.TaskType.String(),
CreatedAt: item.CreatedAt.Format("2006-01-02 15:04:05"), CreatedAt: item.CreatedAt.Format("2006-01-02 15:04:05"),
}) })

View File

@@ -6,6 +6,7 @@ const (
CodeSuccess = 200 CodeSuccess = 200
CodeParamError = 400 CodeParamError = 400
CodeUnauthorized = 401 CodeUnauthorized = 401
CodeTokenExpired = 4011
CodeForbidden = 403 CodeForbidden = 403
CodeNotFound = 404 CodeNotFound = 404
CodeInvalidStatus = 405 CodeInvalidStatus = 405
@@ -23,6 +24,7 @@ const (
CodeSuccessMsg = "success" CodeSuccessMsg = "success"
CodeParamErrorMsg = "param error" CodeParamErrorMsg = "param error"
CodeUnauthorizedMsg = "unauthorized" CodeUnauthorizedMsg = "unauthorized"
CodeTokenExpiredMsg = "token expired"
CodeForbiddenMsg = "forbidden" CodeForbiddenMsg = "forbidden"
CodeNotFoundMsg = "not found" CodeNotFoundMsg = "not found"
CodeInvalidStatusMsg = "invalid status" CodeInvalidStatusMsg = "invalid status"

View File

@@ -4,6 +4,7 @@ import (
"context" "context"
"net/http" "net/http"
"strings" "strings"
"time"
"gitea.com/bitwsd/document_ai/pkg/constant" "gitea.com/bitwsd/document_ai/pkg/constant"
"gitea.com/bitwsd/document_ai/pkg/jwt" "gitea.com/bitwsd/document_ai/pkg/jwt"
@@ -48,15 +49,26 @@ func AuthMiddleware(ctx *gin.Context) {
func MustAuthMiddleware() gin.HandlerFunc { func MustAuthMiddleware() gin.HandlerFunc {
return func(ctx *gin.Context) { return func(ctx *gin.Context) {
token := ctx.GetHeader("Authorization") token := ctx.GetHeader("Authorization")
if token != "" { if token == "" {
ctx.JSON(http.StatusOK, ErrorResponse(ctx, CodeUnauthorized, CodeUnauthorizedMsg))
ctx.Abort()
return
}
token = strings.TrimPrefix(token, "Bearer ") token = strings.TrimPrefix(token, "Bearer ")
claims, err := jwt.ParseToken(token) claims, err := jwt.ParseToken(token)
if err == nil { if err != nil || claims == nil {
ctx.JSON(http.StatusOK, ErrorResponse(ctx, CodeUnauthorized, CodeUnauthorizedMsg))
ctx.Abort()
return
}
if claims.ExpiresAt < time.Now().Unix() {
ctx.JSON(http.StatusOK, ErrorResponse(ctx, CodeTokenExpired, CodeTokenExpiredMsg))
ctx.Abort()
return
}
ctx.Set(constant.ContextUserID, claims.UserId) ctx.Set(constant.ContextUserID, claims.UserId)
} }
} }
}
}
func GetAuthMiddleware() gin.HandlerFunc { func GetAuthMiddleware() gin.HandlerFunc {
return func(ctx *gin.Context) { return func(ctx *gin.Context) {

View File

@@ -64,8 +64,7 @@ func GetPolicyToken() (string, error) {
} }
func GetPolicyURL(ctx context.Context, path string) (string, error) { func GetPolicyURL(ctx context.Context, path string) (string, error) {
// Create OSS client client, err := oss.New(config.GlobalConfig.Aliyun.OSS.Endpoint, config.GlobalConfig.Aliyun.OSS.AccessKeyID, config.GlobalConfig.Aliyun.OSS.AccessKeySecret, oss.UseCname(true))
client, err := oss.New(config.GlobalConfig.Aliyun.OSS.Endpoint, config.GlobalConfig.Aliyun.OSS.AccessKeyID, config.GlobalConfig.Aliyun.OSS.AccessKeySecret)
if err != nil { if err != nil {
log.Error(ctx, "func", "GetPolicyURL", "msg", "create oss client failed", "error", err) log.Error(ctx, "func", "GetPolicyURL", "msg", "create oss client failed", "error", err)
return "", err return "", err
@@ -151,7 +150,7 @@ func DownloadFile(ctx context.Context, ossPath string) (io.ReadCloser, error) {
func GetDownloadURL(ctx context.Context, ossPath string) (string, error) { func GetDownloadURL(ctx context.Context, ossPath string) (string, error) {
endpoint := config.GlobalConfig.Aliyun.OSS.Endpoint endpoint := config.GlobalConfig.Aliyun.OSS.Endpoint
client, err := oss.New(endpoint, config.GlobalConfig.Aliyun.OSS.AccessKeyID, config.GlobalConfig.Aliyun.OSS.AccessKeySecret) client, err := oss.New(endpoint, config.GlobalConfig.Aliyun.OSS.AccessKeyID, config.GlobalConfig.Aliyun.OSS.AccessKeySecret, oss.UseCname(true))
if err != nil { if err != nil {
log.Error(ctx, "func", "GetDownloadURL", "msg", "create oss client failed", "error", err) log.Error(ctx, "func", "GetDownloadURL", "msg", "create oss client failed", "error", err)
return "", err return "", err
@@ -163,11 +162,13 @@ func GetDownloadURL(ctx context.Context, ossPath string) (string, error) {
return "", err return "", err
} }
signURL, err := bucket.SignURL(ossPath, oss.HTTPGet, 60) signURL, err := bucket.SignURL(ossPath, oss.HTTPGet, 3600)
if err != nil { if err != nil {
log.Error(ctx, "func", "GetDownloadURL", "msg", "get object failed", "error", err) log.Error(ctx, "func", "GetDownloadURL", "msg", "get object failed", "error", err)
return "", err return "", err
} }
signURL = strings.Replace(signURL, "http://", "https://", 1)
return signURL, nil return signURL, nil
} }