Compare commits
10 Commits
bb7403f700
...
7c4dfaba54
| Author | SHA1 | Date | |
|---|---|---|---|
| 7c4dfaba54 | |||
| 5ee1cea0d7 | |||
| a538bd6680 | |||
| cd221719cf | |||
| d0c0d2cbc3 | |||
| 930d782f18 | |||
| bdd21c4b0f | |||
| 0aaafdbaa3 | |||
| 68a1755a83 | |||
| 073808eb30 |
@@ -26,6 +26,7 @@ func SetupRouter(engine *gin.RouterGroup) {
|
||||
endpoint := task.NewTaskEndpoint()
|
||||
taskRouter.POST("/evaluate", endpoint.EvaluateTask)
|
||||
taskRouter.GET("/list", common.MustAuthMiddleware(), endpoint.GetTaskList)
|
||||
taskRouter.POST("/export", endpoint.ExportTask)
|
||||
}
|
||||
|
||||
ossRouter := v1.Group("/oss", common.GetAuthMiddleware())
|
||||
|
||||
@@ -61,3 +61,31 @@ func (h *TaskEndpoint) GetTaskList(c *gin.Context) {
|
||||
|
||||
c.JSON(http.StatusOK, common.SuccessResponse(c, resp))
|
||||
}
|
||||
|
||||
func (h *TaskEndpoint) ExportTask(c *gin.Context) {
|
||||
var req task.ExportTaskRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
log.Error(c, "func", "ExportTask", "msg", "Invalid parameters", "error", err)
|
||||
c.JSON(http.StatusOK, common.ErrorResponse(c, common.CodeParamError, "Invalid parameters"))
|
||||
return
|
||||
}
|
||||
fileData, contentType, err := h.taskService.ExportTask(c, &req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, common.ErrorResponse(c, common.CodeSystemError, "导出任务失败"))
|
||||
return
|
||||
}
|
||||
|
||||
// set filename based on export type
|
||||
var filename string
|
||||
switch req.Type {
|
||||
case "pdf":
|
||||
filename = "texpixel_export.pdf"
|
||||
case "docx":
|
||||
filename = "texpixel_export.docx"
|
||||
default:
|
||||
filename = "texpixel_export"
|
||||
}
|
||||
|
||||
c.Header("Content-Disposition", "attachment; filename="+filename)
|
||||
c.Data(http.StatusOK, contentType, fileData)
|
||||
}
|
||||
|
||||
2
go.mod
2
go.mod
@@ -11,6 +11,7 @@ require (
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/jtolds/gls v4.20.0+incompatible
|
||||
github.com/redis/go-redis/v9 v9.7.0
|
||||
github.com/rs/zerolog v1.33.0
|
||||
github.com/spf13/viper v1.19.0
|
||||
@@ -43,6 +44,7 @@ require (
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
|
||||
2
go.sum
2
go.sum
@@ -79,6 +79,7 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
@@ -89,6 +90,7 @@ github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
|
||||
@@ -34,3 +34,8 @@ type TaskListResponse struct {
|
||||
TaskList []*TaskListDTO `json:"task_list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
|
||||
type ExportTaskRequest struct {
|
||||
TaskNo string `json:"task_no" binding:"required"`
|
||||
Type string `json:"type" binding:"required,oneof=pdf docx"`
|
||||
}
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"gitea.com/bitwsd/document_ai/internal/model/task"
|
||||
@@ -111,3 +116,84 @@ func (svc *TaskService) GetTaskList(ctx context.Context, req *task.TaskListReque
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (svc *TaskService) ExportTask(ctx context.Context, req *task.ExportTaskRequest) ([]byte, string, error) {
|
||||
recognitionTask, err := svc.recognitionTaskDao.GetByTaskNo(dao.DB.WithContext(ctx), req.TaskNo)
|
||||
if err != nil {
|
||||
log.Error(ctx, "func", "ExportTask", "msg", "get task by task id failed", "error", err)
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
if recognitionTask == nil {
|
||||
log.Error(ctx, "func", "ExportTask", "msg", "task not found")
|
||||
return nil, "", errors.New("task not found")
|
||||
}
|
||||
|
||||
if recognitionTask.Status != dao.TaskStatusCompleted {
|
||||
log.Error(ctx, "func", "ExportTask", "msg", "task not finished")
|
||||
return nil, "", errors.New("task not finished")
|
||||
}
|
||||
|
||||
recognitionResult, err := svc.recognitionResultDao.GetByTaskID(dao.DB.WithContext(ctx), recognitionTask.ID)
|
||||
if err != nil {
|
||||
log.Error(ctx, "func", "ExportTask", "msg", "get recognition result by task id failed", "error", err)
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
if recognitionResult == nil {
|
||||
log.Error(ctx, "func", "ExportTask", "msg", "recognition result not found")
|
||||
return nil, "", errors.New("recognition result not found")
|
||||
}
|
||||
|
||||
markdown := recognitionResult.Markdown
|
||||
if markdown == "" {
|
||||
log.Error(ctx, "func", "ExportTask", "msg", "markdown not found")
|
||||
return nil, "", errors.New("markdown not found")
|
||||
}
|
||||
|
||||
// call http://localhost:8055/export
|
||||
body := &bytes.Buffer{}
|
||||
writer := multipart.NewWriter(body)
|
||||
_ = writer.WriteField("markdown_input", markdown)
|
||||
_ = writer.WriteField("type", req.Type)
|
||||
writer.Close()
|
||||
|
||||
httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, "http://192.168.5.56:8055/export", body)
|
||||
if err != nil {
|
||||
log.Error(ctx, "func", "ExportTask", "msg", "create http request failed", "error", err)
|
||||
return nil, "", err
|
||||
}
|
||||
httpReq.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(httpReq)
|
||||
if err != nil {
|
||||
log.Error(ctx, "func", "ExportTask", "msg", "http request failed", "error", err)
|
||||
return nil, "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
log.Error(ctx, "func", "ExportTask", "msg", "http request failed", "status", resp.StatusCode)
|
||||
return nil, "", fmt.Errorf("export service returned status: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
fileData, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Error(ctx, "func", "ExportTask", "msg", "read response body failed", "error", err)
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
// determine content type based on export type
|
||||
var contentType string
|
||||
switch req.Type {
|
||||
case "pdf":
|
||||
contentType = "application/pdf"
|
||||
case "docx":
|
||||
contentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
||||
default:
|
||||
contentType = "application/octet-stream"
|
||||
}
|
||||
|
||||
return fileData, contentType, nil
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"gitea.com/bitwsd/document_ai/pkg/requestid"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
)
|
||||
@@ -67,8 +69,13 @@ func log(ctx context.Context, level zerolog.Level, logType LogType, kv ...interf
|
||||
// 添加日志类型
|
||||
event.Str("type", string(logType))
|
||||
|
||||
// 添加请求ID
|
||||
if reqID, exists := ctx.Value("request_id").(string); exists {
|
||||
reqID := requestid.GetRequestID()
|
||||
if reqID == "" {
|
||||
if id, exists := ctx.Value("request_id").(string); exists {
|
||||
reqID = id
|
||||
}
|
||||
}
|
||||
if reqID != "" {
|
||||
event.Str("request_id", reqID)
|
||||
}
|
||||
|
||||
@@ -149,4 +156,3 @@ func Fatal(ctx context.Context, kv ...interface{}) {
|
||||
func Access(ctx context.Context, kv ...interface{}) {
|
||||
log(ctx, zerolog.InfoLevel, TypeAccess, kv...)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"gitea.com/bitwsd/document_ai/pkg/requestid"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func RequestID() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
requestID := c.Request.Header.Get("X-Request-ID")
|
||||
if requestID == "" {
|
||||
requestID = uuid.New().String()
|
||||
reqID := c.Request.Header.Get("X-Request-ID")
|
||||
if reqID == "" {
|
||||
reqID = uuid.New().String()
|
||||
}
|
||||
c.Request.Header.Set("X-Request-ID", requestID)
|
||||
c.Set("request_id", requestID)
|
||||
c.Next()
|
||||
c.Request.Header.Set("X-Request-ID", reqID)
|
||||
c.Set("request_id", reqID)
|
||||
|
||||
requestid.SetRequestID(reqID, func() {
|
||||
c.Next()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
27
pkg/requestid/requestid.go
Normal file
27
pkg/requestid/requestid.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package requestid
|
||||
|
||||
import (
|
||||
"github.com/jtolds/gls"
|
||||
)
|
||||
|
||||
// requestIDKey 是 gls 中存储 request_id 的 key
|
||||
var requestIDKey = gls.GenSym()
|
||||
|
||||
// glsMgr 是 gls 管理器
|
||||
var glsMgr = gls.NewContextManager()
|
||||
|
||||
// SetRequestID 在 gls 中设置 request_id,并在 fn 执行期间保持有效
|
||||
func SetRequestID(requestID string, fn func()) {
|
||||
glsMgr.SetValues(gls.Values{requestIDKey: requestID}, fn)
|
||||
}
|
||||
|
||||
// GetRequestID 从 gls 中获取当前 goroutine 的 request_id
|
||||
func GetRequestID() string {
|
||||
val, ok := glsMgr.GetValue(requestIDKey)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
reqID, _ := val.(string)
|
||||
return reqID
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user