From 587e7a65f00e1d2d9f6209892354b2dae6746cda Mon Sep 17 00:00:00 2001 From: simonzhangsz Date: Thu, 24 Oct 2024 16:18:12 +0800 Subject: [PATCH] add: NBI get fille api --- features/features.go | 5 +- features/nbi/file/controller.go | 257 ++++++++++++++++++++++++++++++++ features/nbi/file/model.go | 47 ++++++ features/nbi/file/route.go | 26 ++++ features/nbi/service.go | 16 ++ lib/file/file_windows.go | 18 ++- 6 files changed, 359 insertions(+), 10 deletions(-) create mode 100644 features/nbi/file/controller.go create mode 100644 features/nbi/file/model.go create mode 100644 features/nbi/file/route.go create mode 100644 features/nbi/service.go diff --git a/features/features.go b/features/features.go index 343ff0bb..e4f68c75 100644 --- a/features/features.go +++ b/features/features.go @@ -3,6 +3,7 @@ package features import ( "be.ems/features/cm" "be.ems/features/lm" + "be.ems/features/nbi" "be.ems/features/pm" "be.ems/lib/log" "github.com/gin-gonic/gin" @@ -12,10 +13,10 @@ func InitServiceEngine(r *gin.Engine) { log.Info("======init feature group gin.Engine") // featuresGroup := r.Group("/") - // 注册 各个features 模块的路由 + // register features routers pm.InitSubServiceRoute(r) lm.InitSubServiceRoute(r) cm.InitSubServiceRoute(r) - + nbi.InitSubServiceRoute(r) // return featuresGroup } diff --git a/features/nbi/file/controller.go b/features/nbi/file/controller.go new file mode 100644 index 00000000..cc5edc88 --- /dev/null +++ b/features/nbi/file/controller.go @@ -0,0 +1,257 @@ +package nbi_file + +import ( + "archive/zip" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "time" + + "be.ems/lib/dborm" + "be.ems/lib/file" + "be.ems/lib/global" + "be.ems/lib/log" + "be.ems/lib/services" + "github.com/gin-gonic/gin" +) + +type SysJobResponse struct { + SysJob + TableName string `json:"tableName"` + TableDisplay string `json:"tableDisplay"` + FilePath string `json:"filePath"` +} + +type TargetParams struct { + Duration int `json:"duration"` + TableName string `json:"tableName"` + Columns string `json:"columns"` // exported column name of time string + TimeCol string `json:"timeCol"` // time stamp of column name + TimeUnit string `json:"timeUnit"` // timestamp unit: second/micro/milli + Extras string `json:"extras"` // extras condition for where + FilePath string `json:"filePath"` // file path +} + +func (m *FileNBI) GetFileList(c *gin.Context) { + var querys FileNBIQuery + + querys.Category = c.Param("category") + querys.Type = c.Param("type") + if err := c.ShouldBindQuery(&querys); err != nil { + c.JSON(http.StatusOK, services.ErrResp(err.Error())) + return + } + + if querys.Path == "" { + tableName := "" + ok := false + switch querys.Category { + case "cdr": + tableName, ok = CDRTableMapper[querys.Type] + if tableName == "" || !ok { + c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid CDR file type: %s", querys.Type))) + return + } + case "log": + tableName, ok = LogTableMapper[querys.Type] + if tableName == "" || !ok { + c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file type: %s", querys.Type))) + return + } + default: + c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file category: %s", querys.Category))) + return + } + + s := SysJob{} + where := fmt.Sprintf("invoke_target='%s' and status=1 and JSON_UNQUOTE(JSON_EXTRACT(target_params,'$.tableName'))='%s'", INVOKE_FILE_EXPORT, tableName) + _, err := dborm.XEngDB().Table(s.TableName()). + Select("JSON_UNQUOTE(JSON_EXTRACT(target_params, '$.filePath')) as file_path"). + Where(where). + Get(&querys.Path) + if err != nil { + c.JSON(http.StatusOK, services.ErrResp(err.Error())) + return + } + + } + + files, err := file.GetFileInfo(querys.Path, querys.Suffix) + if err != nil { + log.Error("failed to GetFileInfo:", err) + c.JSON(http.StatusOK, services.ErrResp(err.Error())) + return + } + + // split files list + lenNum := int64(len(files)) + start := (querys.PageNum - 1) * querys.PageSize + end := start + querys.PageSize + var splitList []file.FileInfo + if start >= lenNum { + splitList = []file.FileInfo{} + } else if end >= lenNum { + splitList = files[start:] + } else { + splitList = files[start:end] + } + total := len(files) + c.JSON(http.StatusOK, services.TotalDataResp(splitList, total)) +} + +func (m *FileNBI) Total(c *gin.Context) { + dir := c.Query("path") + + fileCount, dirCount, err := file.GetFileAndDirCount(dir) + if err != nil { + log.Error("failed to GetFileAndDirCount:", err) + c.JSON(http.StatusOK, services.ErrResp(err.Error())) + return + } + total := fileCount + dirCount + c.JSON(http.StatusOK, services.TotalResp(int64(total))) +} + +func (m *FileNBI) GetSingleFileHandler(c *gin.Context) { + var querys FileNBIQuery + + querys.Category = c.Param("category") + querys.Type = c.Param("type") + querys.DateIndex = c.Param("dateIndex") + if err := c.ShouldBindQuery(&querys); err != nil { + c.JSON(http.StatusOK, services.ErrResp(err.Error())) + return + } + + tableName := "" + if querys.Path == "" { + ok := false + switch querys.Category { + case "cdr": + tableName, ok = CDRTableMapper[querys.Type] + if tableName == "" || !ok { + c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid CDR file type: %s", querys.Type))) + return + } + case "log": + tableName, ok = LogTableMapper[querys.Type] + if tableName == "" || !ok { + c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file type: %s", querys.Type))) + return + } + default: + c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file category: %s", querys.Category))) + return + } + + s := SysJob{} + where := fmt.Sprintf("invoke_target='%s' and status=1 and JSON_UNQUOTE(JSON_EXTRACT(target_params,'$.tableName'))='%s'", INVOKE_FILE_EXPORT, tableName) + _, err := dborm.XEngDB().Table(s.TableName()). + Select("JSON_UNQUOTE(JSON_EXTRACT(target_params, '$.filePath')) as file_path"). + Where(where). + Get(&querys.Path) + if err != nil { + c.JSON(http.StatusOK, services.ErrResp(err.Error())) + return + } + } + + fileName := tableName + "_export_" + querys.DateIndex + "0000" + ".csv" + filePath := filepath.Join(querys.Path, fileName) + + file, err := os.Open(filePath) + if err != nil { + c.JSON(http.StatusOK, services.ErrResp(err.Error())) + return + } + defer file.Close() + + if _, err := os.Stat(filePath); os.IsNotExist(err) { + c.JSON(http.StatusOK, services.ErrResp(err.Error())) + return + } + + c.Header("Content-Disposition", "attachment; filename="+fileName) + c.Header("Content-Type", "application/octet-stream") + c.File(filePath) +} + +func (m *FileNBI) GetMultiFileHandler(c *gin.Context) { + var querys FileNBIQuery + + querys.Category = c.Param("category") + querys.Type = c.Param("type") + if err := c.ShouldBindQuery(&querys); err != nil { + c.JSON(http.StatusOK, services.ErrResp(err.Error())) + return + } + + tableName := "" + if querys.Path == "" { + ok := false + switch querys.Category { + case "cdr": + tableName, ok = CDRTableMapper[querys.Type] + if tableName == "" || !ok { + c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid CDR file type: %s", querys.Type))) + return + } + case "log": + tableName, ok = LogTableMapper[querys.Type] + if tableName == "" || !ok { + c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file type: %s", querys.Type))) + return + } + default: + c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file category: %s", querys.Category))) + return + } + + s := SysJob{} + where := fmt.Sprintf("invoke_target='%s' and status=1 and JSON_UNQUOTE(JSON_EXTRACT(target_params,'$.tableName'))='%s'", INVOKE_FILE_EXPORT, tableName) + _, err := dborm.XEngDB().Table(s.TableName()). + Select("JSON_UNQUOTE(JSON_EXTRACT(target_params, '$.filePath')) as file_path"). + Where(where). + Get(&querys.Path) + if err != nil { + c.JSON(http.StatusOK, services.ErrResp(err.Error())) + return + } + } + + zipWriter := zip.NewWriter(c.Writer) + defer zipWriter.Close() + + for _, fileName := range querys.FileNames { + filePath := filepath.Join(querys.Path, fileName) + + file, err := os.Open(filePath) + if err != nil { + c.JSON(http.StatusOK, services.ErrResp(err.Error())) + return + } + defer file.Close() + + if _, err := os.Stat(filePath); os.IsNotExist(err) { + c.JSON(http.StatusOK, services.ErrResp(err.Error())) + return + } + writer, err := zipWriter.Create(filepath.Base(fileName)) + if err != nil { + c.JSON(http.StatusOK, services.ErrResp(err.Error())) + return + } + + if _, err := io.Copy(writer, file); err != nil { + c.JSON(http.StatusOK, services.ErrResp(err.Error())) + return + } + + } + zipFile := tableName + "_export_" + time.Now().Local().Format(global.DateData) + ".zip" + c.Header("Content-Disposition", "attachment; filename="+zipFile) + c.Header("Content-Type", "application/zip") + //c.File(filePath) +} diff --git a/features/nbi/file/model.go b/features/nbi/file/model.go new file mode 100644 index 00000000..5dcdd9fa --- /dev/null +++ b/features/nbi/file/model.go @@ -0,0 +1,47 @@ +package nbi_file + +import ( + "be.ems/lib/file" +) + +const ( + INVOKE_FILE_EXPORT = "exportTable" +) + +var CDRTableMapper map[string]string = map[string]string{ + "ims": "cdr_event_ims", + "smf": "cdr_event_smf", + "smsc": "cdr_event_smsc", + "sms": "cdr_event_smsc", +} + +var LogTableMapper map[string]string = map[string]string{ + "operate": "sys_log_operate", + "security": "sys_log_login", + "alarm": "alarm_log", +} + +type SysJob struct { + JobID int64 `gorm:"column:job_id;primary_key;auto_increment" json:"job_id"` //任务ID + InvokeTarget string `gorm:"column:invoke_target" json:"invoke_target"` //调用目标字符串 + TargetParams string `gorm:"column:target_params;type:json" json:"target_params,omitempty"` //调用目标传入参数 +} + +func (s *SysJob) TableName() string { + return "sys_job" +} + +type FileNBI struct { + file.FileInfo +} + +type FileNBIQuery struct { + Category string `form:"category" binding:"required"` + Type string `form:"type" binding:"required"` + DateIndex string `form:"dateIndex"` + Path string `json:"path" form:"path"` + FileNames []string `json:"fileName" form:"fileName"` + Suffix string `form:"suffix"` + PageNum int64 `form:"pageNum"` + PageSize int64 `form:"pageSize"` +} diff --git a/features/nbi/file/route.go b/features/nbi/file/route.go new file mode 100644 index 00000000..f0cb58f6 --- /dev/null +++ b/features/nbi/file/route.go @@ -0,0 +1,26 @@ +package nbi_file + +import ( + "be.ems/src/framework/middleware" + "github.com/gin-gonic/gin" +) + +// Register Routes for file_export +func Register(r *gin.RouterGroup) { + fileNBI := r.Group("/file") + { + var f *FileNBI + fileNBI.GET("/:category/:type/list", + middleware.PreAuthorize(nil), + f.GetFileList, + ) + fileNBI.GET("/:category/:type/:dateIndex", + middleware.PreAuthorize(nil), + f.GetSingleFileHandler, + ) + fileNBI.GET("/:category/:type", + middleware.PreAuthorize(nil), + f.GetMultiFileHandler, + ) + } +} diff --git a/features/nbi/service.go b/features/nbi/service.go new file mode 100644 index 00000000..7b913d5c --- /dev/null +++ b/features/nbi/service.go @@ -0,0 +1,16 @@ +// log management package + +package nbi + +import ( + nbi_file "be.ems/features/nbi/file" + "be.ems/lib/log" + "github.com/gin-gonic/gin" +) + +func InitSubServiceRoute(r *gin.Engine) { + log.Info("======init North-Bound Interface group gin.Engine") + + nbiGroup := r.Group("/nbi") + nbi_file.Register(nbiGroup) +} diff --git a/lib/file/file_windows.go b/lib/file/file_windows.go index fbcf9b3c..7c97f111 100644 --- a/lib/file/file_windows.go +++ b/lib/file/file_windows.go @@ -9,14 +9,15 @@ import ( ) type FileInfo struct { - FileType string `json:"fileType"` // 文件类型 - FileMode string `json:"fileMode"` // 文件的权限 - LinkCount int64 `json:"linkCount"` // 硬链接数目 - Owner string `json:"owner"` // 所属用户 - Group string `json:"group"` // 所属组 - Size int64 `json:"size"` // 文件的大小 - ModifiedTime int64 `json:"modifiedTime"` // 最后修改时间,单位为秒 - FileName string `json:"fileName"` // 文件的名称 + FileType string `json:"fileType"` // file type: file/directory + FileMode string `json:"fileMode"` // file mode + LinkCount int64 `json:"linkCount"` // link count + Owner string `json:"owner"` // owner + Group string `json:"group"` // group + Size int64 `json:"size"` // size: xx byte + ModifiedTime int64 `json:"modifiedTime"` // last modified time:seconds + FilePath string `json:"filePath"` // file path + FileName string `json:"fileName"` // file name } func GetFileInfo(dir, suffix string) ([]FileInfo, error) { @@ -48,6 +49,7 @@ func GetFileInfo(dir, suffix string) ([]FileInfo, error) { Group: "-", Size: info.Size(), ModifiedTime: info.ModTime().Unix(), + FilePath: dir, FileName: info.Name(), } files = append(files, fileInfo)