瀏覽代碼

feat: 添加仿真测试数据上传

HeWang 8 月之前
父節點
當前提交
2f0b5f7ee4

+ 12 - 0
biz/dal/mysql/simulation_test_record.go

@@ -2,6 +2,7 @@ package mysql
 
 import (
 	"context"
+	"fmt"
 	"pji_desktop_http/biz/dal/query"
 	"pji_desktop_http/biz/model"
 )
@@ -11,3 +12,14 @@ func AddSimulationTestRecords(ctx context.Context, records []*model.SimulationTe
 	err := r.WithContext(ctx).Create(records...)
 	return err
 }
+
+func QuerySimulationTestRecords(ctx context.Context, sceneId string, testTime string) ([]*model.SimulationTestRecord, error) {
+	r := query.SimulationTestRecord
+	records, err := r.WithContext(ctx).Where(r.SceneID.Eq(sceneId), r.TestTime.Eq(testTime)).Order(r.Round.Asc()).Find()
+	if err != nil {
+		fmt.Println("Query simulation records failed:", err.Error())
+		return nil, err
+	}
+	fmt.Print("Query simulation records successfully:", records)
+	return records, err
+}

+ 1 - 2
biz/handler/map_service/map_service.go

@@ -19,9 +19,8 @@ import (
 // CheckMapBufConsistency 检查请求id对应的mapBuf文件夹的一致性
 // @router /map/checkmapbuf [POST]
 func CheckMapBufConsistency(ctx context.Context, c *app.RequestContext) {
-	var err error
 	var req []string
-	err = c.BindAndValidate(&req)
+	err := c.BindAndValidate(&req)
 	if err != nil {
 		c.String(consts.StatusBadRequest, err.Error())
 		return

+ 158 - 0
biz/handler/simulation_service/simulation_service.go

@@ -3,6 +3,7 @@ package simulation_service
 import (
 	"archive/zip"
 	"context"
+	"encoding/json"
 	"fmt"
 	"github.com/cloudwego/hertz/pkg/app"
 	"github.com/cloudwego/hertz/pkg/protocol/consts"
@@ -331,3 +332,160 @@ func AddSimulationRecord(ctx context.Context, c *app.RequestContext) {
 	}
 	c.JSON(consts.StatusOK, entity.HttpResult{Status: true, Code: "", Message: "仿真测试记录添加成功"})
 }
+
+// QueryEvalRecord 查询算法评价记录(根据场景id及时间戳)
+// @router /simulation/query/eval/record [GET]
+func QueryEvalRecord(ctx context.Context, c *app.RequestContext) {
+	sceneId := c.Query("sceneId")
+	fmt.Println("sceneId", sceneId)
+
+	testTime := c.Query("testTime")
+	fmt.Println("testTime", testTime)
+
+	records, err := mysql.QuerySimulationTestRecords(ctx, sceneId, testTime)
+	if err != nil {
+		c.JSON(consts.StatusOK, entity.HttpResult{Status: false, Code: "", Message: "仿真测试记录查询失败", Details: ""})
+		return
+	}
+	output, err := json.Marshal(records)
+	if err != nil {
+		c.JSON(consts.StatusOK, entity.HttpResult{Status: false, Code: "", Message: "仿真测试记录查询失败", Details: ""})
+		return
+	}
+	c.JSON(consts.StatusOK, entity.HttpResult{Status: true, Code: "", Message: "仿真测试记录查询成功", Details: string(output)})
+}
+
+// DownloadFileByKeys 给定object key数组从oss下载(打包)文件
+// @router /simulation/download/oss/key [POST]
+func DownloadFileByKeys(ctx context.Context, c *app.RequestContext) {
+	sceneId := c.Query("sceneId")
+	fmt.Println("sceneId", sceneId)
+
+	typeName := c.Query("typeName")
+	fmt.Println("typeName", typeName)
+
+	var req []string
+	err := c.BindAndValidate(&req)
+	if err != nil {
+		c.String(consts.StatusBadRequest, err.Error())
+		return
+	}
+	fmt.Println("req", req)
+	if len(req) == 0 {
+		c.JSON(consts.StatusBadRequest, entity.HttpResult{Status: false, Code: "", Message: "请求数据为空。"})
+	} else if len(req) == 1 { // 只有一条数据则直接下载文件
+		objectKey := req[0]
+		// 从OSS下载文件
+		reader, err := config.OssBucket.GetObject(objectKey)
+
+		if err != nil {
+			c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
+			return
+		}
+		defer reader.Close()
+
+		// 设置响应头
+		c.Response.Header.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filepath.Base(objectKey)))
+		c.Response.Header.Set("Content-Type", "binary/octet-stream")
+
+		// 将文件流式传输回客户端
+		data, err := io.ReadAll(reader)
+		if err != nil {
+			panic(err)
+		}
+		if _, err := c.Write(data); err != nil {
+			c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
+			return
+		}
+	} else { // 多条数据先打包后下载文件
+		fileName := sceneId + "_" + typeName + ".zip"
+		filePath, tmpDir, err := generateZipByKey(ctx, req, fileName)
+		if err != nil {
+			c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
+		}
+		fmt.Println("filePath", filePath)
+
+		// 检查文件是否存在
+		if _, err := os.Stat(filePath); os.IsNotExist(err) {
+			c.JSON(http.StatusNotFound, map[string]string{"error": "File not found"})
+			return
+		}
+
+		// 打开文件
+		f, err := os.Open(filePath)
+		if err != nil {
+			c.JSON(http.StatusInternalServerError, map[string]string{"error": "Failed to open file"})
+			return
+		}
+		defer f.Close()
+
+		// 设置响应头
+		c.Response.Header.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filepath.Base(filePath)))
+		c.Response.Header.Set("Content-Type", "binary/octet-stream")
+
+		// 将文件流式传输回客户端
+		data, err := io.ReadAll(f)
+		if err != nil {
+			panic(err)
+		}
+		if _, err := c.Write(data); err != nil {
+			c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
+			return
+		}
+		defer os.RemoveAll(tmpDir)
+	}
+}
+
+// 根据object keys生成压缩包
+func generateZipByKey(ctx context.Context, keys []string, fileName string) (file string, tmpDir string, err error) {
+	// 创建临时文件夹
+	tmpDir, err = os.MkdirTemp("", "temp-download-*")
+
+	fmt.Println("tmpDir:", tmpDir)
+	if err != nil {
+		fmt.Println("Error creating temporary directory:", err)
+		return "", "", err
+	}
+	c_log.GlobalLogger.Info("创建下载-临时文件夹:", tmpDir)
+
+	// 创建根文件夹(文件打包的根目录)
+	baseDir := filepath.Join(tmpDir, "data")
+	if err := os.Mkdir(baseDir, 0755); err != nil {
+		fmt.Println("Error creating subdirectory:", err)
+		return "", "", err
+	}
+	c_log.GlobalLogger.Info("创建文件打包根目录:", baseDir)
+
+	// 从oss下载文件到根目录
+	for _, file := range keys {
+		err = config.OssBucket.GetObjectToFile(file, filepath.Join(baseDir, filepath.Base(file)))
+		if err != nil {
+			fmt.Println("Error downloading file:", file, err)
+			return "", "", err
+		}
+	}
+	c_log.GlobalLogger.Info("下载oss文件到根目录 - 成功")
+
+	// 创建压缩文件
+	zipPath := filepath.Join(tmpDir, fileName)
+	zipFile, err := os.Create(zipPath)
+	if err != nil {
+		fmt.Println("Error creating ZIP file:", err)
+		return "", "", err
+	}
+	defer zipFile.Close()
+
+	zipWriter := zip.NewWriter(zipFile)
+	defer zipWriter.Close()
+
+	// 压缩文件夹
+	if err := util.AddDirToZip(baseDir, zipWriter); err != nil {
+		fmt.Println("Error adding directory to ZIP:", err)
+		return "", "", err
+	}
+	fmt.Println("ZIP file created successfully.")
+
+	c_log.GlobalLogger.Info("创建压缩文件 - 成功")
+
+	return zipPath, tmpDir, nil
+}

+ 4 - 0
router.go

@@ -47,4 +47,8 @@ func customizedRegister(r *server.Hertz) {
 	r.GET("/simulation/check/file/data/status", simulation_service.CheckDataFileStatus)
 
 	r.POST("/simulation/add/record", simulation_service.AddSimulationRecord)
+
+	r.GET("/simulation/query/eval/record", simulation_service.QueryEvalRecord)
+
+	r.POST("/simulation/download/oss/key", simulation_service.DownloadFileByKeys)
 }