Parcourir la source

watch preloads file to autoload

yinbangzhong il y a 2 ans
Parent
commit
500985cf75
5 fichiers modifiés avec 211 ajouts et 98 suppressions
  1. 11 7
      controllers/audio.go
  2. 18 2
      docs/docs.go
  3. 18 2
      docs/swagger.json
  4. 12 2
      docs/swagger.yaml
  5. 152 85
      service/process.go

+ 11 - 7
controllers/audio.go

@@ -7,6 +7,7 @@ import (
 	"gorm.io/gorm"
 	"io"
 	"mime/multipart"
+	"net/url"
 	"os"
 	"path"
 	"path/filepath"
@@ -28,14 +29,16 @@ type AudioCtl struct{}
 // Upload
 // @Tags      音频
 // @Summary   上传音频
+// @Accept     multipart/form-data
 // @Produce   application/json
-// @Param files formData []file false "多文件上传"
+// @Param file formData []file false "多文件上传"
 // @Success   200 {object} util.Response "成功"
 // @Router    /api-sa/v1/audio/upload [post]
 func (slf AudioCtl) Upload(c *gin.Context) {
 	var headers []*multipart.FileHeader
-	if len(c.Request.MultipartForm.File["file"]) > 1 {
-		headers = c.Request.MultipartForm.File["file"]
+	files, _ := c.MultipartForm()
+	if len(files.File["file"]) > 1 {
+		headers = files.File["file"]
 	} else {
 		util.ResponseFormat(c, code.RequestParamError, "文件需要一一对应")
 		return
@@ -89,7 +92,7 @@ func (slf AudioCtl) Upload(c *gin.Context) {
 			//解析 交路号:123_公里标:321
 			fileds := string(bts)
 			arr = strings.Split(fileds, "_")
-			if len(arr) > 1 {
+			if len(arr) != 2 {
 				util.ResponseFormat(c, code.RequestParamError, "文件内容格式不对")
 				return
 			} else {
@@ -291,8 +294,9 @@ func (slf AudioCtl) AudioDownload(c *gin.Context) {
 	}
 	if params.Filetype == 2 {
 		filepath = audio.TxtFilePath
-		//设置Content-Type为txt文件类型
-		c.Header("Content-Type", "text/plain")
+		//设置Content-Type为txt文件类型,避免中文乱码
+		c.Header("Content-Type", "text/plain; charset=utf-8")
+		c.Header("Content-Transfer-Encoding", "binary")
 	}
 	if filepath == "" {
 		util.ResponseFormat(c, code.InternalError, "查询失败")
@@ -312,7 +316,7 @@ func (slf AudioCtl) AudioDownload(c *gin.Context) {
 		return
 	}
 
-	c.Header("Content-Disposition", "inline; filename="+audio.Name) // 在浏览器中直接打开
+	c.Header("Content-Disposition", "inline; filename="+url.PathEscape(audio.Name)) // 在浏览器中直接打开
 	c.Header("Content-Length", fmt.Sprint(fileInfo.Size()))
 
 	if _, err := io.Copy(c.Writer, file); err != nil {

+ 18 - 2
docs/docs.go

@@ -115,6 +115,11 @@ const docTemplate = `{
                 ],
                 "summary": "音频下载",
                 "parameters": [
+                    {
+                        "type": "integer",
+                        "name": "fileType",
+                        "in": "query"
+                    },
                     {
                         "type": "integer",
                         "name": "id",
@@ -196,6 +201,11 @@ const docTemplate = `{
                 ],
                 "summary": "音频详情,含解析结果",
                 "parameters": [
+                    {
+                        "type": "integer",
+                        "name": "fileType",
+                        "in": "query"
+                    },
                     {
                         "type": "integer",
                         "name": "id",
@@ -457,6 +467,9 @@ const docTemplate = `{
         },
         "/api-sa/v1/audio/upload": {
             "post": {
+                "consumes": [
+                    "multipart/form-data"
+                ],
                 "produces": [
                     "application/json"
                 ],
@@ -472,7 +485,7 @@ const docTemplate = `{
                         },
                         "collectionFormat": "csv",
                         "description": "多文件上传",
-                        "name": "files",
+                        "name": "file",
                         "in": "formData"
                     }
                 ],
@@ -697,7 +710,7 @@ const docTemplate = `{
                     "type": "integer"
                 },
                 "station": {
-                    "description": "车站",
+                    "description": "公里标",
                     "type": "string"
                 },
                 "trainNumber": {
@@ -822,6 +835,9 @@ const docTemplate = `{
                 "id"
             ],
             "properties": {
+                "fileType": {
+                    "type": "integer"
+                },
                 "id": {
                     "type": "integer"
                 }

+ 18 - 2
docs/swagger.json

@@ -104,6 +104,11 @@
                 ],
                 "summary": "音频下载",
                 "parameters": [
+                    {
+                        "type": "integer",
+                        "name": "fileType",
+                        "in": "query"
+                    },
                     {
                         "type": "integer",
                         "name": "id",
@@ -185,6 +190,11 @@
                 ],
                 "summary": "音频详情,含解析结果",
                 "parameters": [
+                    {
+                        "type": "integer",
+                        "name": "fileType",
+                        "in": "query"
+                    },
                     {
                         "type": "integer",
                         "name": "id",
@@ -446,6 +456,9 @@
         },
         "/api-sa/v1/audio/upload": {
             "post": {
+                "consumes": [
+                    "multipart/form-data"
+                ],
                 "produces": [
                     "application/json"
                 ],
@@ -461,7 +474,7 @@
                         },
                         "collectionFormat": "csv",
                         "description": "多文件上传",
-                        "name": "files",
+                        "name": "file",
                         "in": "formData"
                     }
                 ],
@@ -686,7 +699,7 @@
                     "type": "integer"
                 },
                 "station": {
-                    "description": "车站",
+                    "description": "公里标",
                     "type": "string"
                 },
                 "trainNumber": {
@@ -811,6 +824,9 @@
                 "id"
             ],
             "properties": {
+                "fileType": {
+                    "type": "integer"
+                },
                 "id": {
                     "type": "integer"
                 }

+ 12 - 2
docs/swagger.yaml

@@ -89,7 +89,7 @@ definitions:
         description: 音频大小
         type: integer
       station:
-        description: 车站
+        description: 公里标
         type: string
       trainNumber:
         description: 车次
@@ -170,6 +170,8 @@ definitions:
     type: object
   request.ProcessAudio:
     properties:
+      fileType:
+        type: integer
       id:
         type: integer
     required:
@@ -267,6 +269,9 @@ paths:
   /api-sa/v1/audio/download:
     get:
       parameters:
+      - in: query
+        name: fileType
+        type: integer
       - in: query
         name: id
         required: true
@@ -313,6 +318,9 @@ paths:
   /api-sa/v1/audio/info:
     get:
       parameters:
+      - in: query
+        name: fileType
+        type: integer
       - in: query
         name: id
         required: true
@@ -483,13 +491,15 @@ paths:
       - 音频
   /api-sa/v1/audio/upload:
     post:
+      consumes:
+      - multipart/form-data
       parameters:
       - collectionFormat: csv
         description: 多文件上传
         in: formData
         items:
           type: file
-        name: files
+        name: file
         type: array
       produces:
       - application/json

+ 152 - 85
service/process.go

@@ -165,6 +165,10 @@ func PreLoad(cxt context.Context) {
 	if mkdirErr != nil {
 		logx.Errorf("function os.MkdirAll() err:%v", mkdirErr)
 	}
+	mkdirErr1 := os.MkdirAll(conf.LocalConf.StorePath, os.ModePerm)
+	if mkdirErr1 != nil {
+		logx.Errorf("function os.MkdirAll() err:%v", mkdirErr1)
+	}
 	//文件夹下新增音频文件时触发
 	watcher, err := fsnotify.NewWatcher()
 	if err != nil {
@@ -175,6 +179,111 @@ func PreLoad(cxt context.Context) {
 	if err != nil {
 		log.Fatal(err)
 	}
+
+	audoF := func(eventName, fileName string, audio *models.Audio) bool {
+		time.Sleep(time.Second * 1)
+		//设置文件访问权限
+		err = os.Chmod(eventName, 0777)
+		if err != nil {
+			logx.Errorf(fmt.Sprintf("%s:%s", eventName, "设置文件权限失败"))
+		}
+
+		//校验文件命名
+		arr := strings.Split(fileName, "_")
+		if len(arr) != 6 {
+			logx.Errorf(fmt.Sprintf("%s:%s", fileName, "文件名称错误"))
+			return false
+		}
+		timeStr := arr[4] + strings.Split(arr[5], ".")[0]
+		t, err := time.ParseInLocation("20060102150405", timeStr, time.Local)
+		if err != nil {
+			logx.Errorf(fmt.Sprintf("%s:%s", fileName, "时间格式不对"))
+		}
+
+		//查重
+		_, err = models.NewAudioSearch().SetName(fileName).First()
+		if err != gorm.ErrRecordNotFound {
+			logx.Errorf(fmt.Sprintf("%s:%s", fileName, "重复上传"))
+			return false
+		}
+
+		//将文件移动到uploads文件夹下
+		//判断storePath中末尾是否带
+		var src string
+		if strings.HasSuffix(conf.LocalConf.StorePath, "/") {
+			src = conf.LocalConf.StorePath + fileName
+		} else {
+			src = conf.LocalConf.StorePath + "/" + fileName
+		}
+		err = os.Rename(eventName, src)
+		if err != nil {
+			logx.Errorf(fmt.Sprintf("%s:%s", fileName, "移动文件失败"))
+			return false
+		}
+		// 读取文件大小
+		fileInfo, err := os.Stat(src)
+		if err != nil {
+			logx.Errorf(fmt.Sprintf("%s:%s", fileName, "获取文件大小失败"))
+			return false
+		}
+		size := fileInfo.Size()
+		fmt.Println("fileName:", fileName, "size:", size, "src1", src)
+
+		audio.Name = fileName
+		audio.Size = size
+		audio.FilePath = src
+		audio.AudioStatus = constvar.AudioStatusUploadOk
+		audio.LocomotiveNumber = arr[0]
+		audio.TrainNumber = arr[1]
+		audio.DriverNumber = arr[2]
+		audio.Station = arr[3]
+		audio.OccurrenceAt = t
+		audio.IsFollowed = 0
+		return true
+	}
+
+	txtF := func(filePath string, audio *models.Audio) bool {
+		fileName := filepath.Base(filePath)
+		//读取filepath文件内容到bts
+		bts, err := os.ReadFile(filePath)
+		if err != nil {
+			logx.Errorf(fmt.Sprintf("%s:%s", filePath, "读取txt文件失败"))
+			return false
+		}
+		//解析 交路号:123_公里标:321
+		fileds := string(bts)
+		arr := strings.Split(fileds, "_")
+		if len(arr) != 2 {
+			logx.Errorf(fmt.Sprintf("%s:%s", filePath, "读取txt文件内容格式不对"))
+			return false
+		} else {
+			RouteNumber := strings.Split(arr[0], ":")
+			KilometerMarker := strings.Split(arr[1], ":")
+			if len(RouteNumber) > 1 && len(KilometerMarker) > 1 {
+				audio.RouteNumber = RouteNumber[1]
+				audio.KilometerMarker = KilometerMarker[1]
+			} else {
+				logx.Errorf(fmt.Sprintf("%s:%s", filePath, "文件内容格式不对"))
+				return false
+			}
+		}
+		var src string
+		if strings.HasSuffix(conf.LocalConf.StorePath, "/") {
+			src = conf.LocalConf.StorePath + fileName
+		} else {
+			src = conf.LocalConf.StorePath + "/" + fileName
+		}
+		err = os.Rename(filePath, src)
+		if err != nil {
+			logx.Errorf(fmt.Sprintf("%s:%s", fileName, "移动文件失败"))
+			return false
+		}
+		audio.TxtFilePath = src
+		return true
+	}
+
+	//成对变量
+	pair := make(map[string]string)
 FOR:
 	for {
 		select {
@@ -186,98 +295,56 @@ FOR:
 				continue
 			}
 			if event.Op&fsnotify.Create == fsnotify.Create {
-				// 判断文件类型是否为.mp3或.wav
-				if filepath.Ext(event.Name) == ".mp3" || filepath.Ext(event.Name) == ".wav" {
-					time.Sleep(time.Second * 1)
-					//设置文件访问权限
-					err = os.Chmod(event.Name, 0777)
-					if err != nil {
-						logx.Errorf(fmt.Sprintf("%s:%s", event.Name, "设置文件权限失败"))
-					}
-					// 文件名
-					fileName := filepath.Base(event.Name)
-					//校验文件命名
-					arr := strings.Split(fileName, "_")
-					if len(arr) != 6 {
-						logx.Errorf(fmt.Sprintf("%s:%s", fileName, "文件名称错误"))
-						continue
-					}
-					timeStr := arr[4] + strings.Split(arr[5], ".")[0]
-					t, err := time.ParseInLocation("20060102150405", timeStr, time.Local)
-					if err != nil {
-						logx.Errorf(fmt.Sprintf("%s:%s", fileName, "时间格式不对"))
-					}
-
-					//查重
-					_, err = models.NewAudioSearch().SetName(fileName).First()
-					if err != gorm.ErrRecordNotFound {
-						logx.Errorf(fmt.Sprintf("%s:%s", fileName, "重复上传"))
-						continue
+				// 文件名
+				fileName := filepath.Base(event.Name)
+				//获取不带扩展名的文件名
+				name := strings.TrimSuffix(fileName, filepath.Ext(fileName))
+				//判断文件在pair中
+				if _, ok := pair[name]; !ok {
+					pair[name] = event.Name
+				} else {
+					audio := &models.Audio{}
+					isOk := true
+					// 判断文件类型是否为.mp3或.wav
+					if filepath.Ext(event.Name) == ".mp3" || filepath.Ext(event.Name) == ".wav" {
+						isOk = audoF(event.Name, fileName, audio) && txtF(pair[name], audio)
 					}
-
-					//将文件移动到uploads文件夹下
-					//判断storePath中末尾是否带
-					var src string
-					if strings.HasSuffix(conf.LocalConf.StorePath, "/") {
-						src = conf.LocalConf.StorePath + fileName
-					} else {
-						src = conf.LocalConf.StorePath + "/" + fileName
+					if filepath.Ext(event.Name) == ".txt" {
+						isOk = audoF(pair[name], filepath.Base(pair[name]), audio) && txtF(event.Name, audio)
 					}
-					err = os.Rename(event.Name, src)
-					if err != nil {
-						logx.Errorf(fmt.Sprintf("%s:%s", fileName, "移动文件失败"))
+					if !isOk {
+						delete(pair, name)
 						continue
 					}
-					// 读取文件大小
-					fileInfo, err := os.Stat(src)
-					if err != nil {
-						logx.Errorf(fmt.Sprintf("%s:%s", fileName, "获取文件大小失败"))
-						continue
-					}
-					size := fileInfo.Size()
-					fmt.Println("fileName:", fileName, "size:", size, "src1", src)
-
-					audio := &models.Audio{
-						Name:             fileName,
-						Size:             size,
-						FilePath:         src,
-						AudioStatus:      constvar.AudioStatusUploadOk,
-						LocomotiveNumber: arr[0],
-						TrainNumber:      arr[1],
-						DriverNumber:     arr[2],
-						Station:          arr[3],
-						OccurrenceAt:     t,
-						IsFollowed:       0,
-					}
-
-					if err = models.NewAudioSearch().Create(audio); err != nil {
-						logx.Errorf(fmt.Sprintf("%s:%s", fileName, "数据库create失败"))
-						continue
-					}
-
-					go func() {
-						var trainInfoNames = []string{arr[0], arr[1], arr[3]} //
-						var (
-							info   *models.TrainInfo
-							err    error
-							parent models.TrainInfo
-						)
-						for i := 0; i < 3; i++ {
-							name := trainInfoNames[i]
-							class := constvar.Class(i + 1)
-							info, err = models.NewTrainInfoSearch().SetName(name).SetClass(class).First()
-							if err == gorm.ErrRecordNotFound {
-								info = &models.TrainInfo{
-									Name:     name,
-									Class:    class,
-									ParentID: parent.ID,
+					if len(audio.Name) > 0 {
+						if err = models.NewAudioSearch().Create(audio); err != nil {
+							logx.Errorf(fmt.Sprintf("%s:%s", fileName, "数据库create失败"))
+							continue
+						}
+						go func() {
+							var trainInfoNames = []string{audio.LocomotiveNumber, audio.TrainNumber, audio.Station} //
+							var (
+								info   *models.TrainInfo
+								err    error
+								parent models.TrainInfo
+							)
+							for i := 0; i < 3; i++ {
+								name := trainInfoNames[i]
+								class := constvar.Class(i + 1)
+								info, err = models.NewTrainInfoSearch().SetName(name).SetClass(class).First()
+								if err == gorm.ErrRecordNotFound {
+									info = &models.TrainInfo{
+										Name:     name,
+										Class:    class,
+										ParentID: parent.ID,
+									}
+									_ = models.NewTrainInfoSearch().Create(info)
 								}
-								_ = models.NewTrainInfoSearch().Create(info)
+								parent = *info
 							}
-							parent = *info
-						}
 
-					}()
+						}()
+					}
 				}
 			}
 		case err, ok := <-watcher.Errors: