Browse Source

feat:添加地图bag下载接口

HeWang 10 months ago
parent
commit
f8ee0b3fcb
6 changed files with 316 additions and 27 deletions
  1. 297 23
      biz/handler/map_service/map_service.go
  2. 5 0
      common/config/c_map.go
  3. 3 3
      common/config/c_pji.go
  4. 4 1
      main.go
  5. 6 0
      router.go
  6. 1 0
      test/map_test.go

+ 297 - 23
biz/handler/map_service/map_service.go

@@ -1,21 +1,25 @@
 package map_service
 
 import (
+	"archive/zip"
 	"context"
 	"encoding/json"
 	"fmt"
 	"github.com/cloudwego/hertz/pkg/app"
 	"github.com/cloudwego/hertz/pkg/protocol/consts"
+	"io"
 	"io/ioutil"
 	"net/http"
+	"os"
+	"path/filepath"
 	"pji_desktop_http/common/config"
 	"pji_desktop_http/common/entity"
 	"pji_desktop_http/common/util"
 	"strings"
 )
 
-// CheckMapBufConsistency .
-// @router /map/checkmapbuf [GET]
+// CheckMapBufConsistency 检查请求id对应的mapBuf文件夹的一致性
+// @router /map/checkmapbuf [POST]
 func CheckMapBufConsistency(ctx context.Context, c *app.RequestContext) {
 	var err error
 	var req []string
@@ -33,26 +37,20 @@ func CheckMapBufConsistency(ctx context.Context, c *app.RequestContext) {
 		c.JSON(consts.StatusOK, entity.HttpResult{Status: true, Code: "", Message: "mapBuf文件夹数据一致。"})
 	} else {
 		var firstValue int
-		for i, v := range req {
+		for i, id := range req {
 			// 根据id获取对应的oss文件列表
-			fileList, err := getFileObjectBYId(v)
+			fileList, err := getExactedMapFileById(id)
+			// 过滤特定后缀的文件列表
+			fileList = filterBySuffixes(fileList, config.Filtersuffixes...)
+			//fmt.Println("Filtered Strings:", fileList)
+
 			if err != nil {
 				c.String(consts.StatusBadRequest, err.Error())
 				return
 			}
 
-			// 过滤特定后缀的文件列表
-			suffixes := []string{
-				"map.pgm",
-				"map.yaml",
-				"map.json",
-				"forbid_area.json",
-			}
-			filteredFileList := filterBySuffixes(fileList, suffixes...)
-			fmt.Println("Filtered Strings:", filteredFileList)
-
 			// 获取文件列表的总大小
-			totalSize := calculateTotalFileSize(filteredFileList)
+			totalSize := calculateTotalFileSize(fileList)
 			fmt.Println("Total Size:", totalSize)
 
 			// 判断不同文件列表(mapBuf)中文件的总大小是否一致
@@ -70,15 +68,124 @@ func CheckMapBufConsistency(ctx context.Context, c *app.RequestContext) {
 	}
 }
 
-// 根据id获取对应的oss文件列表
-func getFileObjectBYId(id string) (fileList []string, err error) {
+// DownloadOSSFile 根据objectKey下载指定的oss文件
+// @router /map/downloadossfile [GET]
+func DownloadOSSFile(ctx context.Context, c *app.RequestContext) {
+	objectKey := "pjibot/pjibot-P1YNYD1M229000129/data_merge/2024-07-10-09-08-58_obstacledetection_30.bag"
+	// 从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
+	}
+}
+
+// DownLoadZipFile 根据请求id从oss拉取并打包下载建图所需要的文件
+// @router /map/downloadmapzipfile   [GET]
+func DownLoadMapZipFile(ctx context.Context, c *app.RequestContext) {
+	id := c.Query("id")
+	fmt.Println(id)
+
+	// 根据id生成用于地图更新的压缩包
+	filePath, tmpDir, err := generateZipById(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)
+}
+
+// DownLoadMapBagFile 根据请求id从oss拉取并下载解析后的map.bag文件
+// @router /map/downloadmapbagfile   [GET]
+func DownLoadMapBagFile(ctx context.Context, c *app.RequestContext) {
+	id := c.Query("id")
+	fmt.Println("id: ", id)
+
+	// 根据id获取对应的oss文件列表
+	fileList, err := getExactedMapFileById(id)
+	// 过滤特定后缀的文件列表
+	fileList = filterBySuffixes(fileList, "map.bag")
+	//fmt.Println("fileList", fileList)
+
+	objectKey := fileList[0]
+	// 从OSS下载文件
+	reader, err := config.OssBucket.GetObject(objectKey)
+
+	if err != nil {
+		c.JSON(consts.StatusInternalServerError, entity.HttpResult{Status: false, Code: "", Message: "解析地图Bag下载失败。"})
+		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(consts.StatusInternalServerError, entity.HttpResult{Status: false, Code: "", Message: "解析地图Bag下载失败。"})
+		return
+	}
+	c.JSON(consts.StatusOK, entity.HttpResult{Status: true, Code: "", Message: "解析地图Bag下载成功。"})
+}
+
+// 根据id获取解析后的地图文件列表
+func getExactedMapFileById(id string) (fileList []string, err error) {
 	url := config.SenceOssDownUrl + id
 
 	// 构建请求
 	req, err := http.NewRequest("GET", url, nil)
 	if err != nil {
 		fmt.Println("Error creating request:", err)
-		return
+		return nil, err
 	}
 
 	// 添加认证头
@@ -89,7 +196,7 @@ func getFileObjectBYId(id string) (fileList []string, err error) {
 	resp, err := client.Do(req)
 	if err != nil {
 		fmt.Println("Error executing request:", err)
-		return
+		return nil, err
 	}
 
 	defer resp.Body.Close()
@@ -103,7 +210,7 @@ func getFileObjectBYId(id string) (fileList []string, err error) {
 	dataField, ok := data["data"].([]interface{})
 	if !ok {
 		fmt.Println("Error extracting data field")
-		return
+		return nil, err
 	}
 
 	// 转换字符串切片
@@ -111,12 +218,134 @@ func getFileObjectBYId(id string) (fileList []string, err error) {
 		str, ok := item.(string)
 		if !ok {
 			fmt.Println("Error converting item to string")
-			return
+			return nil, err
 		}
 		fileList = append(fileList, str)
 	}
 
-	return fileList, err
+	return fileList, nil
+}
+
+// 根据id获取对应的原始bag文件
+func getRosFileById(id string) (file string, err error) {
+	url := config.SenceInfoUrl + id
+
+	// 构建请求
+	req, err := http.NewRequest("GET", url, nil)
+	if err != nil {
+		fmt.Println("Error creating request:", err)
+		return "", err
+	}
+
+	// 添加认证头
+	req.Header.Set("Authorization", config.Token)
+
+	// 发送请求
+	client := &http.Client{}
+	resp, err := client.Do(req)
+	if err != nil {
+		fmt.Println("Error executing request:", err)
+		return "", err
+	}
+
+	defer resp.Body.Close()
+	body, _ := ioutil.ReadAll(resp.Body)
+
+	// Json转换为map
+	var data map[string]interface{}
+	err = json.Unmarshal(body, &data)
+
+	//fmt.Println("data:", data)
+	// 提取响应体中的data字段
+	dataField, ok := data["data"].(map[string]interface{})
+	if !ok {
+		fmt.Println("Error extracting data field")
+		return "", err
+	}
+	// 从 data字段中提取 rosField
+	rosField, ok := dataField["rosFileId"].(string)
+	if !ok {
+		fmt.Println("ID not found or not a string")
+		return
+	}
+	if !ok {
+		fmt.Println("Error extracting rosFileId field")
+		return "", err
+	}
+	//println("rosFileId:", rosField)
+
+	return rosField, nil
+}
+
+// 根据id生成用于地图更新的压缩包
+func generateZipById(id string) (file string, tmpDir string, err error) {
+	// 根据id获取对应的oss文件列表
+	fileList, err := getExactedMapFileById(id)
+	// 过滤特定后缀的文件列表
+	fileList = filterBySuffixes(fileList, config.Filtersuffixes...)
+	//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
+	}
+
+	// 创建根文件夹(文件打包的根目录)
+	baseDir := filepath.Join(tmpDir, "data")
+	if err := os.Mkdir(baseDir, 0755); err != nil {
+		fmt.Println("Error creating subdirectory:", err)
+		return "", "", err
+	}
+	// 创建子文件夹 mapBuf
+	subDir := filepath.Join(baseDir, "mapBuf")
+	if err := os.Mkdir(subDir, 0755); err != nil {
+		fmt.Println("Error creating subdirectory:", err)
+		return "", "", err
+	}
+
+	// 从oss下载文件到 mapBuf文件夹
+	for _, file := range fileList {
+		err = config.OssBucket.GetObjectToFile(file, filepath.Join(subDir, filepath.Base(file)))
+		if err != nil {
+			fmt.Println("Error downloading mapBuf file:", err)
+			return "", "", err
+		}
+	}
+
+	// 从oss下载bag文件到 data文件夹
+	RosFileId, _ := getRosFileById(id)
+	err = config.OssBucket.GetObjectToFile(RosFileId, filepath.Join(baseDir, filepath.Base(RosFileId)))
+	if err != nil {
+		fmt.Println("Error downloading Bag file:", err)
+		return "", "", err
+	}
+
+	// 创建压缩文件
+	zipPath := filepath.Join(tmpDir, "mapFile-"+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 := addDirToZip(baseDir, zipWriter); err != nil {
+		fmt.Println("Error adding directory to ZIP:", err)
+		return "", "", err
+	}
+	fmt.Println("ZIP file created successfully.")
+
+	return zipPath, tmpDir, nil
 }
 
 // 从字符串切片中筛选出以特定后缀结尾的字符串
@@ -124,7 +353,11 @@ func filterBySuffixes(strList []string, suffixes ...string) []string {
 	var filtered []string
 	for _, s := range strList {
 		for _, suffix := range suffixes {
-			if strings.HasSuffix(s, suffix) {
+			//if strings.HasSuffix(s, suffix) {
+			//	filtered = append(filtered, s)
+			//	break
+			//}
+			if filepath.Base(s) == suffix {
 				filtered = append(filtered, s)
 				break
 			}
@@ -145,3 +378,44 @@ 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()
+
+		header, err := zip.FileInfoHeader(info)
+		if err != nil {
+			return err
+		}
+
+		// Adjust the header name to reflect the relative path in the ZIP file
+		header.Name = strings.TrimPrefix(path, dirPath)
+		header.Name = filepath.ToSlash(header.Name)
+
+		writer, err := zipWriter.CreateHeader(header)
+		if err != nil {
+			return err
+		}
+
+		if _, err := io.Copy(writer, file); err != nil {
+			return err
+		}
+
+		return nil
+	})
+
+	return nil
+}

+ 5 - 0
common/config/c_map.go

@@ -0,0 +1,5 @@
+package config
+
+var (
+	Filtersuffixes = []string{"map.pgm", "map.yaml", "map.json", "forbid_area.json"}
+)

+ 3 - 3
common/config/c_pji.go

@@ -1,8 +1,8 @@
 package config
 
 var (
-	SenceOssDownUrl string = "http://36.110.106.156:11121/open/scene/oss/down/"
-	SenceInfoUrl    string = "http://36.110.106.156:11121/open/scene/"
+	SenceOssDownUrl = "http://36.110.106.156:11121/open/scene/oss/down/"
+	SenceInfoUrl    = "http://36.110.106.156:11121/open/scene/"
 
-	Token string = "4773hd92ysj54paflw2jem3onyhywxt2"
+	Token = "4773hd92ysj54paflw2jem3onyhywxt2"
 )

+ 4 - 1
main.go

@@ -13,7 +13,10 @@ func main() {
 	dal.Init()
 	c_log.InitLog("logs/", "desktop_http")
 	config.InitOssConfig()
-	h := server.Default()
+	//h := server.Default()
+	h := server.New(
+		server.WithStreamBody(true),
+	)
 	register(h)
 	h.Spin()
 }

+ 6 - 0
router.go

@@ -17,4 +17,10 @@ func customizedRegister(r *server.Hertz) {
 
 	r.POST("/map/checkmapbuf", map_service.CheckMapBufConsistency)
 
+	r.GET("/map/downloadossfile", map_service.DownloadOSSFile)
+
+	r.GET("/map/downloadmapzipfile", map_service.DownLoadMapZipFile)
+
+	r.GET("/map/downloadmapbagfile", map_service.DownLoadMapBagFile)
+
 }

+ 1 - 0
test/map_test.go

@@ -0,0 +1 @@
+package test