Просмотр исходного кода

add:增加上传报告文件的接口

zqbao 3 месяцев назад
Родитель
Сommit
0a311bf110
6 измененных файлов с 200 добавлено и 8 удалено
  1. 12 5
      config/config.go
  2. 34 0
      controller/knowledge/knowledge.go
  3. 2 0
      init_serve/router.go
  4. 13 0
      routers/knowledge.go
  5. 95 0
      services/knowledge/knowledge.go
  6. 44 3
      utils/common.go

+ 12 - 5
config/config.go

@@ -1,11 +1,12 @@
 package config
 
 type Config struct {
-	Log   Log   `mapstructure:"log" json:"log" yaml:"log"`
-	Serve Serve `mapstructure:"serve" json:"serve" yaml:"serve"`
-	Mysql Mysql `mapstructure:"mysql" json:"mysql" yaml:"mysql"`
-	Redis Redis `mapstructure:"redis" json:"redis" yaml:"redis"`
-	Gn    Gn    `mapstructure:"gn" json:"gn" yaml:"gn"`
+	Log       Log       `mapstructure:"log" json:"log" yaml:"log"`
+	Serve     Serve     `mapstructure:"serve" json:"serve" yaml:"serve"`
+	Mysql     Mysql     `mapstructure:"mysql" json:"mysql" yaml:"mysql"`
+	Redis     Redis     `mapstructure:"redis" json:"redis" yaml:"redis"`
+	Gn        Gn        `mapstructure:"gn" json:"gn" yaml:"gn"`
+	EtaReport EtaReport `mapstructure:"eta-report" json:"eta-report" yaml:"eta-report"`
 }
 
 // Serve gin服务配置
@@ -91,3 +92,9 @@ type Gn struct {
 	DefaultUserPass     string `mapstructure:"default-user-pass" json:"default-user-pass" yaml:"default-user-pass" description:"默认密码"`
 	OAHost              string `mapstructure:"oa-host" json:"oa-host" yaml:"oa-host" description:"oa服务地址"`
 }
+
+type EtaReport struct {
+	Host   string `mapstructure:"host" json:"host" yaml:"host" description:"eta-report服务地址"`
+	AppId  string `mapstructure:"app-id" json:"app-id" yaml:"app-id" description:"eta-report服务app-id"`
+	Secret string `mapstructure:"secret" json:"secret" yaml:"secret" description:"eta-report服务secret"`
+}

+ 34 - 0
controller/knowledge/knowledge.go

@@ -0,0 +1,34 @@
+package knowledge
+
+import (
+	"encoding/json"
+	"eta_gn/eta_bridge/controller/resp"
+	"eta_gn/eta_bridge/global"
+	"eta_gn/eta_bridge/services/knowledge"
+
+	"github.com/gin-gonic/gin"
+)
+
+type KnowledgeController struct{}
+
+// Save 存储
+func (k *KnowledgeController) Save(c *gin.Context) {
+	res, err := knowledge.ForwardRequest(c, global.CONFIG.EtaReport.Host+"v1/report/knowledge/upload")
+	if err != nil {
+		global.LOG.Error("knowledge save error: ", err)
+		resp.Fail("保存失败", c)
+		return
+	}
+	var result knowledge.KnowledgeUploadResp
+	if e := json.Unmarshal(res, &result); e != nil {
+		global.LOG.Error("knowledge save unmarshal error: ", e)
+		resp.Fail("保存失败", c)
+		return
+	}
+	if result.Ret != 200 {
+		global.LOG.Info("knowledgeResp Ret:%d, Msg:%s, ErrMsg:%s ", result.Ret, result.Msg, result.ErrMsg)
+		resp.Fail("保存失败", c)
+	}
+
+	resp.Ok("保存成功", c)
+}

+ 2 - 0
init_serve/router.go

@@ -5,6 +5,7 @@ import (
 	"eta_gn/eta_bridge/global"
 	"eta_gn/eta_bridge/middleware"
 	"eta_gn/eta_bridge/routers"
+
 	"github.com/gin-gonic/gin"
 )
 
@@ -23,5 +24,6 @@ func InitRouter() (r *gin.Engine) {
 	routers.InitAuth(rBase)
 	routers.InitIndexData(rBase)
 	routers.InitGn(rBase)
+	routers.InitKnowledgeRouter(rBase)
 	return
 }

+ 13 - 0
routers/knowledge.go

@@ -0,0 +1,13 @@
+package routers
+
+import (
+	"eta_gn/eta_bridge/controller/knowledge"
+
+	"github.com/gin-gonic/gin"
+)
+
+func InitKnowledgeRouter(r *gin.RouterGroup) {
+	control := new(knowledge.KnowledgeController)
+	group := r.Group("knowledge/")
+	group.POST("save", control.Save)
+}

+ 95 - 0
services/knowledge/knowledge.go

@@ -0,0 +1,95 @@
+package knowledge
+
+import (
+	"bytes"
+	"eta_gn/eta_bridge/global"
+	"eta_gn/eta_bridge/utils"
+	"io"
+	"mime/multipart"
+	"net/http"
+	"strconv"
+	"time"
+
+	"github.com/gin-gonic/gin"
+)
+
+type KnowledgeUploadResp struct {
+	Ret     int
+	Msg     string
+	ErrMsg  string `json:"-"`
+	Success bool   `description:"true 执行成功,false 执行失败"`
+}
+
+func ForwardRequest(c *gin.Context, targetURL string) (responseBody []byte, err error) {
+	// 获取文件
+	form, err := c.MultipartForm()
+	if err != nil {
+		return
+	}
+
+	// 将文件数据重新封装为multipart/form-data格式
+	body := new(bytes.Buffer)
+	writer := multipart.NewWriter(body)
+
+	// 将原请求的文件添加到新的multipart请求体中
+	for _, files := range form.File {
+		for _, file := range files {
+			part, er := writer.CreateFormFile(file.Filename, file.Filename)
+			if er != nil {
+				err = er
+				return
+			}
+
+			// 打开文件并写入到multipart的部分
+			fileContent, er := file.Open()
+			if er != nil {
+				err = er
+				return
+			}
+			_, er = io.Copy(part, fileContent)
+			if er != nil {
+				err = er
+				return
+			}
+		}
+	}
+
+	// 将body的内容写入
+	for k, v := range c.Request.PostForm {
+		for _, value := range v {
+			writer.WriteField(k, value)
+		}
+	}
+	writer.Close()
+
+	// 2. 构造一个新的请求并转发
+	req, err := http.NewRequest(c.Request.Method, targetURL, body)
+	if err != nil {
+		return
+	}
+
+	// 设置Content-Type为multipart/form-data
+	req.Header.Set("Content-Type", writer.FormDataContentType())
+	nonce := utils.GetRandStringNoSpecialChar(32)
+	timeStamp := time.Now().UnixMilli() / 1000
+	signature := utils.GetSign(global.CONFIG.EtaReport.AppId, global.CONFIG.EtaReport.Secret, nonce, strconv.Itoa(int(timeStamp)))
+	req.Header.Set("nonce", utils.GetRandStringNoSpecialChar(32))
+	req.Header.Set("timestamp", strconv.Itoa(int(timeStamp)))
+	req.Header.Set("appid", global.CONFIG.EtaReport.AppId)
+	req.Header.Set("signature", signature)
+
+	// 3. 执行请求并处理响应
+	client := &http.Client{}
+	resp, err := client.Do(req)
+	if err != nil {
+		return
+	}
+	defer resp.Body.Close()
+
+	// 将目标服务的响应写回给客户端
+	responseBody, err = io.ReadAll(resp.Body)
+	if err != nil {
+		return
+	}
+	return
+}

+ 44 - 3
utils/common.go

@@ -2,16 +2,15 @@ package utils
 
 import (
 	"bufio"
+	"crypto/hmac"
 	"crypto/md5"
 	"crypto/sha1"
+	"crypto/sha256"
 	"encoding/base64"
 	"encoding/hex"
 	"encoding/json"
 	"errors"
 	"fmt"
-	"github.com/astaxie/beego/logs"
-	"github.com/dgrijalva/jwt-go"
-	"gorm.io/gorm"
 	"image"
 	"image/png"
 	"io"
@@ -21,9 +20,14 @@ import (
 	"os"
 	"path"
 	"regexp"
+	"sort"
 	"strconv"
 	"strings"
 	"time"
+
+	"github.com/astaxie/beego/logs"
+	"github.com/dgrijalva/jwt-go"
+	"gorm.io/gorm"
 )
 
 var ErrNoRow = gorm.ErrRecordNotFound
@@ -1057,3 +1061,40 @@ func IsErrNoRow(err error) bool {
 	}
 	return errors.Is(err, gorm.ErrRecordNotFound)
 }
+
+// HmacSha256 计算HmacSha256
+// key 是加密所使用的key
+// data 是加密的内容
+func HmacSha256(key string, data string) []byte {
+	mac := hmac.New(sha256.New, []byte(key))
+	_, _ = mac.Write([]byte(data))
+
+	return mac.Sum(nil)
+}
+
+// HmacSha256ToBase64 将加密后的二进制转Base64字符串
+func HmacSha256ToBase64(key string, data string) string {
+	return base64.URLEncoding.EncodeToString(HmacSha256(key, data))
+}
+
+func GetSign(appId, secret, nonce, timestamp string) (sign string) {
+	signStrMap := map[string]string{
+		"nonce":     nonce,
+		"timestamp": timestamp,
+		"appid":     appId,
+	}
+	keys := make([]string, 0, len(signStrMap))
+	for k := range signStrMap {
+		keys = append(keys, k)
+	}
+	sort.Strings(keys)
+	var signStr string
+	for _, k := range keys {
+		signStr += k + "=" + signStrMap[k] + "&"
+	}
+	signStr = strings.Trim(signStr, "&")
+	fmt.Println("signStr:" + signStr)
+	sign = HmacSha256ToBase64(secret, signStr)
+	fmt.Println("sign:" + sign)
+	return
+}