watch preloads file to autoload
| | |
| | | "gorm.io/gorm" |
| | | "io" |
| | | "mime/multipart" |
| | | "net/url" |
| | | "os" |
| | | "path" |
| | | "path/filepath" |
| | |
| | | // 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 |
| | |
| | | //解析 交路号:123_公里标:321 |
| | | fileds := string(bts) |
| | | arr = strings.Split(fileds, "_") |
| | | if len(arr) > 1 { |
| | | if len(arr) != 2 { |
| | | util.ResponseFormat(c, code.RequestParamError, "文件内容格式不对") |
| | | return |
| | | } else { |
| | |
| | | } |
| | | 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, "查询失败") |
| | |
| | | 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 { |
| | |
| | | "parameters": [ |
| | | { |
| | | "type": "integer", |
| | | "name": "fileType", |
| | | "in": "query" |
| | | }, |
| | | { |
| | | "type": "integer", |
| | | "name": "id", |
| | | "in": "query", |
| | | "required": true |
| | |
| | | ], |
| | | "summary": "音频详情,含解析结果", |
| | | "parameters": [ |
| | | { |
| | | "type": "integer", |
| | | "name": "fileType", |
| | | "in": "query" |
| | | }, |
| | | { |
| | | "type": "integer", |
| | | "name": "id", |
| | |
| | | }, |
| | | "/api-sa/v1/audio/upload": { |
| | | "post": { |
| | | "consumes": [ |
| | | "multipart/form-data" |
| | | ], |
| | | "produces": [ |
| | | "application/json" |
| | | ], |
| | |
| | | }, |
| | | "collectionFormat": "csv", |
| | | "description": "多文件上传", |
| | | "name": "files", |
| | | "name": "file", |
| | | "in": "formData" |
| | | } |
| | | ], |
| | |
| | | "type": "integer" |
| | | }, |
| | | "station": { |
| | | "description": "车站", |
| | | "description": "公里标", |
| | | "type": "string" |
| | | }, |
| | | "trainNumber": { |
| | |
| | | "id" |
| | | ], |
| | | "properties": { |
| | | "fileType": { |
| | | "type": "integer" |
| | | }, |
| | | "id": { |
| | | "type": "integer" |
| | | } |
| | |
| | | "parameters": [ |
| | | { |
| | | "type": "integer", |
| | | "name": "fileType", |
| | | "in": "query" |
| | | }, |
| | | { |
| | | "type": "integer", |
| | | "name": "id", |
| | | "in": "query", |
| | | "required": true |
| | |
| | | ], |
| | | "summary": "音频详情,含解析结果", |
| | | "parameters": [ |
| | | { |
| | | "type": "integer", |
| | | "name": "fileType", |
| | | "in": "query" |
| | | }, |
| | | { |
| | | "type": "integer", |
| | | "name": "id", |
| | |
| | | }, |
| | | "/api-sa/v1/audio/upload": { |
| | | "post": { |
| | | "consumes": [ |
| | | "multipart/form-data" |
| | | ], |
| | | "produces": [ |
| | | "application/json" |
| | | ], |
| | |
| | | }, |
| | | "collectionFormat": "csv", |
| | | "description": "多文件上传", |
| | | "name": "files", |
| | | "name": "file", |
| | | "in": "formData" |
| | | } |
| | | ], |
| | |
| | | "type": "integer" |
| | | }, |
| | | "station": { |
| | | "description": "车站", |
| | | "description": "公里标", |
| | | "type": "string" |
| | | }, |
| | | "trainNumber": { |
| | |
| | | "id" |
| | | ], |
| | | "properties": { |
| | | "fileType": { |
| | | "type": "integer" |
| | | }, |
| | | "id": { |
| | | "type": "integer" |
| | | } |
| | |
| | | description: 音频大小 |
| | | type: integer |
| | | station: |
| | | description: 车站 |
| | | description: 公里标 |
| | | type: string |
| | | trainNumber: |
| | | description: 车次 |
| | |
| | | type: object |
| | | request.ProcessAudio: |
| | | properties: |
| | | fileType: |
| | | type: integer |
| | | id: |
| | | type: integer |
| | | required: |
| | |
| | | get: |
| | | parameters: |
| | | - in: query |
| | | name: fileType |
| | | type: integer |
| | | - in: query |
| | | name: id |
| | | required: true |
| | | type: integer |
| | |
| | | /api-sa/v1/audio/info: |
| | | get: |
| | | parameters: |
| | | - in: query |
| | | name: fileType |
| | | type: integer |
| | | - in: query |
| | | name: id |
| | | required: true |
| | |
| | | - 音频 |
| | | /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 |
| | |
| | | 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 { |
| | |
| | | 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 { |
| | |
| | | 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) |
| | | //获取不带扩展名的文件名 |
| | | 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) |
| | | } |
| | | // 文件名 |
| | | fileName := filepath.Base(event.Name) |
| | | //校验文件命名 |
| | | arr := strings.Split(fileName, "_") |
| | | if len(arr) != 6 { |
| | | logx.Errorf(fmt.Sprintf("%s:%s", fileName, "文件名称错误")) |
| | | if filepath.Ext(event.Name) == ".txt" { |
| | | isOk = audoF(pair[name], filepath.Base(pair[name]), audio) && txtF(event.Name, audio) |
| | | } |
| | | if !isOk { |
| | | delete(pair, name) |
| | | 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 |
| | | } |
| | | |
| | | //将文件移动到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(event.Name, src) |
| | | if err != nil { |
| | | logx.Errorf(fmt.Sprintf("%s:%s", fileName, "移动文件失败")) |
| | | 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, |
| | | } |
| | | _ = models.NewTrainInfoSearch().Create(info) |
| | | } |
| | | parent = *info |
| | | 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) |
| | | } |
| | | parent = *info |
| | | } |
| | | |
| | | }() |
| | | }() |
| | | } |
| | | } |
| | | } |
| | | case err, ok := <-watcher.Errors: |