ソースを参照

feat: 添加仿真数据压缩包下载

HeWang 9 ヶ月 前
コミット
7c4acac3fa

+ 13 - 1
biz/dal/mysql/world.go

@@ -2,14 +2,26 @@ package mysql
 
 import (
 	"context"
+	"fmt"
 	"pji_desktop_http/biz/dal/query"
 	"pji_desktop_http/biz/model"
 )
 
-func TestAddWorld(ctx context.Context, world model.World) {
+func AddWorld(ctx context.Context, world model.World) {
 	w := query.World
 	err := w.WithContext(ctx).Create(&world)
 	if err != nil {
 		panic(err)
 	}
 }
+
+func QueryWorld(ctx context.Context, sceneId string) (*model.World, error) {
+	w := query.World
+	world, err := w.WithContext(ctx).Where(w.SceneID.Eq(sceneId)).Order(w.CreatedAt.Desc()).First()
+	if err != nil {
+		fmt.Println("query world failed:", err.Error())
+		return nil, err
+	}
+	fmt.Print("query world successfully:", world)
+	return world, err
+}

+ 9 - 53
biz/handler/map_service/map_service.go

@@ -94,14 +94,14 @@ func DownloadOSSFile(ctx context.Context, c *app.RequestContext) {
 	}
 }
 
-// DownLoadZipFile 根据请求id从oss拉取并打包下载建图所需要的文件
+// DownloadMapZipFile 根据请求id从oss拉取并打包下载建图所需要的文件
 // @router /map/downloadmapzipfile   [GET]
-func DownLoadMapZipFile(ctx context.Context, c *app.RequestContext) {
+func DownloadMapZipFile(ctx context.Context, c *app.RequestContext) {
 	id := c.Query("id")
 	fmt.Println(id)
 
 	// 根据id生成用于地图更新的压缩包
-	filePath, tmpDir, err := generateZipById(id)
+	filePath, tmpDir, err := generateMapZipById(id)
 	if err != nil {
 		c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
 	}
@@ -137,9 +137,9 @@ func DownLoadMapZipFile(ctx context.Context, c *app.RequestContext) {
 	defer os.RemoveAll(tmpDir)
 }
 
-// DownLoadMapBagFile 根据请求id从oss拉取并下载解析后的map.bag文件
+// DownloadMapBagFile 根据请求id从oss拉取并下载解析后的map.bag文件
 // @router /map/downloadmapbagfile   [GET]
-func DownLoadMapBagFile(ctx context.Context, c *app.RequestContext) {
+func DownloadMapBagFile(ctx context.Context, c *app.RequestContext) {
 	id := c.Query("id")
 	fmt.Println("id: ", id)
 
@@ -177,12 +177,12 @@ func DownLoadMapBagFile(ctx context.Context, c *app.RequestContext) {
 }
 
 // 根据id生成用于地图更新的压缩包
-func generateZipById(id string) (file string, tmpDir string, err error) {
+func generateMapZipById(id string) (file string, tmpDir string, err error) {
 	// 根据id获取对应的oss文件列表
 	allFileList, err := util.GetExactedMapFileById(id)
 
 	// 过滤特定后缀的文件列表
-	mapBuFileList := util.FilterBySuffixes(allFileList, config.MapBufFiltersuffixes...)
+	mapBufFileList := util.FilterBySuffixes(allFileList, config.MapBufFiltersuffixes...)
 	//fmt.Println("Filtered Strings:", fileList)
 	if err != nil {
 		return
@@ -242,7 +242,7 @@ func generateZipById(id string) (file string, tmpDir string, err error) {
 	c_log.GlobalLogger.Info("下载文件到bag_folder文件夹 - 成功")
 
 	// 从oss下载文件到 mapBuf 文件夹
-	for _, file := range mapBuFileList {
+	for _, file := range mapBufFileList {
 		err = config.OssBucket.GetObjectToFile(file, filepath.Join(mapBufDir, filepath.Base(file)))
 		if err != nil {
 			fmt.Println("Error downloading mapBuf file:", err)
@@ -276,7 +276,7 @@ func generateZipById(id string) (file string, tmpDir string, err error) {
 	defer zipWriter.Close()
 
 	// 压缩文件夹
-	if err := addDirToZip(baseDir, zipWriter); err != nil {
+	if err := util.AddDirToZip(baseDir, zipWriter); err != nil {
 		fmt.Println("Error adding directory to ZIP:", err)
 		return "", "", err
 	}
@@ -299,47 +299,3 @@ func calculateTotalFileSize(fileList []string) int {
 	}
 	return totalSize
 }
-
-// 压缩文件夹
-func addDirToZip(dirPath string, zipWriter *zip.Writer) error {
-	filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
-		if err != nil {
-			return err
-		}
-
-		if info.IsDir() {
-			return nil
-		}
-
-		file, err := os.Open(path)
-		if err != nil {
-			return err
-		}
-		defer file.Close()
-
-		// 处理路径,确保保留相对路径结构
-		relPath, err := filepath.Rel(dirPath, path)
-		if err != nil {
-			return err
-		}
-		header, err := zip.FileInfoHeader(info)
-		if err != nil {
-			return err
-		}
-
-		header.Name = filepath.ToSlash(relPath)
-
-		writer, err := zipWriter.CreateHeader(header)
-		if err != nil {
-			return err
-		}
-
-		if _, err := io.Copy(writer, file); err != nil {
-			return err
-		}
-
-		return nil
-	})
-
-	return nil
-}

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

@@ -0,0 +1,140 @@
+package simulation_service
+
+import (
+	"archive/zip"
+	"context"
+	"fmt"
+	"github.com/cloudwego/hertz/pkg/app"
+	"io"
+	"net/http"
+	"os"
+	"path/filepath"
+	"pji_desktop_http/biz/dal/mysql"
+	"pji_desktop_http/common/config"
+	"pji_desktop_http/common/config/c_log"
+	"pji_desktop_http/common/util"
+)
+
+// DownloadSimulationZipFile 根据请求id从oss拉取并打包仿真测试所需要的文件
+// @router /simulation/download/zipfile   [GET]
+func DownloadSimulationZipFile(ctx context.Context, c *app.RequestContext) {
+	id := c.Query("id")
+	fmt.Println(id)
+
+	// 根据id生成用于地图更新的压缩包
+	filePath, tmpDir, err := generateSimulationZipById(ctx, id)
+	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)
+}
+
+// 根据id生成用于仿真测试的压缩包
+func generateSimulationZipById(ctx context.Context, id string) (file string, tmpDir string, err error) {
+	// 根据id获取对应的oss文件列表
+	allFileList, err := util.GetExactedMapFileById(id)
+
+	//fmt.Println("Filtered Strings:", fileList)
+	if err != nil {
+		return
+	}
+
+	// 创建临时文件夹
+	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下载data.zip文件到根目录(data.zip中的mapBuf文件夹包含map.pgm, map.yaml)
+	// 过滤特定后缀的文件列表
+	simulationFileList := util.FilterBySuffixes(allFileList, config.SimulationFiltersuffixes...)
+	// 从oss下载文件到 根目录
+	for _, file := range simulationFileList {
+		err = config.OssBucket.GetObjectToFile(file, filepath.Join(baseDir, filepath.Base(file)))
+		if err != nil {
+			fmt.Println("Error downloading mapBuf file:", err)
+			return "", "", err
+		}
+	}
+	c_log.GlobalLogger.Info("下载data.zip文件到根目录 - 成功")
+
+	// 下载world文件
+	// 查询状态
+	world, err := mysql.QueryWorld(ctx, id)
+	if err != nil || world == nil { // 文件不存在
+		c_log.GlobalLogger.Info("world文件不存在 - 跳过")
+	} else { // 文件存在
+		// 下载文件
+		worldURL := world.WorldURL
+		err = config.OssBucket.GetObjectToFile(worldURL, filepath.Join(baseDir, filepath.Base(worldURL)))
+		if err != nil {
+			fmt.Println("Error downloading world file:", err)
+			return "", "", err
+		}
+		c_log.GlobalLogger.Info("下载world文件到根目录 - 成功")
+	}
+
+	// 创建压缩文件
+	zipPath := filepath.Join(tmpDir, "simulationFile-"+id+".zip")
+	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
+}

+ 16 - 2
biz/handler/world_service/world_service.go

@@ -15,7 +15,7 @@ import (
 )
 
 // UploadWorldFile 将world文件上传到oss
-// @router /world/uploadworldfile [GET]
+// @router /world/upload/worldfile [GET]
 func UploadWorldFile(ctx context.Context, c *app.RequestContext) {
 
 	equipmentNo := c.Query("equipmentNo")
@@ -52,5 +52,19 @@ func UploadWorldFile(ctx context.Context, c *app.RequestContext) {
 
 	// 保存world记录到数据库
 	world := model.World{ID: uuid.NewV1().String(), SceneID: sceneNo, WorldURL: ossWorldObjectKey}
-	mysql.TestAddWorld(ctx, world)
+	mysql.AddWorld(ctx, world)
+}
+
+// CheckWorldFileStatus 检查world文件oss中是否存在
+// @router /world/check/file/status [GET]
+func CheckWorldFileStatus(ctx context.Context, c *app.RequestContext) {
+	sceneID := c.Query("sceneID")
+	fmt.Println("sceneID", sceneID)
+
+	world, err := mysql.QueryWorld(ctx, sceneID)
+	if err != nil || world == nil {
+		c.JSON(consts.StatusOK, entity.HttpResult{Status: false, Code: "", Message: "world文件不存在"})
+		return
+	}
+	c.JSON(consts.StatusOK, entity.HttpResult{Status: true, Code: "", Message: "world文件已存在"})
 }

+ 1 - 2
biz/model/world.go

@@ -5,9 +5,8 @@
 package model
 
 import (
-	"time"
-
 	"gorm.io/gorm"
+	"time"
 )
 
 const TableNameWorld = "world"

+ 1 - 0
common/config/c_map.go

@@ -4,4 +4,5 @@ var (
 	MapBufFiltersuffixes      = []string{"map.pgm", "map.yaml", "map.json", "forbid_area.json"}
 	BuildMapBagFiltersuffixes = []string{"build_map.bag"}
 	OriginMapFiltersuffixes   = []string{"map.pgm", "map.yaml"}
+	SimulationFiltersuffixes  = []string{"data.zip"}
 )

+ 12 - 7
router.go

@@ -6,6 +6,7 @@ import (
 	"github.com/cloudwego/hertz/pkg/app/server"
 	handler "pji_desktop_http/biz/handler"
 	"pji_desktop_http/biz/handler/map_service"
+	"pji_desktop_http/biz/handler/simulation_service"
 	"pji_desktop_http/biz/handler/user_service"
 	"pji_desktop_http/biz/handler/world_service"
 )
@@ -14,17 +15,21 @@ import (
 func customizedRegister(r *server.Hertz) {
 	r.GET("/ping", handler.Ping)
 
-	r.GET("/test/queryuser", user_service.TestQueryUser)
+	r.GET("/test/query/user", user_service.TestQueryUser)
 
-	r.POST("/map/checkmapbufconsistency", map_service.CheckMapBufConsistency)
+	r.POST("/map/check/mapbufconsistency", map_service.CheckMapBufConsistency)
 
-	r.GET("/map/downloadossfile", map_service.DownloadOSSFile)
+	r.GET("/map/download/ossfile", map_service.DownloadOSSFile)
 
-	r.GET("/map/downloadmapzipfile", map_service.DownLoadMapZipFile)
+	r.GET("/map/download/zipfile", map_service.DownloadMapZipFile)
 
-	r.GET("/map/downloadmapbagfile", map_service.DownLoadMapBagFile)
+	r.GET("/map/download/mapbagfile", map_service.DownloadMapBagFile)
 
-	r.GET("/world/uploadworldfile", world_service.UploadWorldFile)
-	r.POST("/world/uploadworldfile", world_service.UploadWorldFile)
+	r.GET("/world/upload/worldfile", world_service.UploadWorldFile)
+	r.POST("/world/upload/worldfile", world_service.UploadWorldFile)
+
+	r.GET("/world/check/file/status", world_service.CheckWorldFileStatus)
+
+	r.GET("/simulation/download/zipfile", simulation_service.DownloadSimulationZipFile)
 
 }