task_conf.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. package task
  2. import (
  3. "bufio"
  4. "bytes"
  5. "context"
  6. "crypto/md5"
  7. "encoding/hex"
  8. "errors"
  9. "fmt"
  10. "github.com/qiniu/api.v7/v7/auth/qbox"
  11. "github.com/qiniu/api.v7/v7/storage"
  12. "go.uber.org/zap"
  13. "gorm.io/gorm"
  14. "io"
  15. "log-server/global"
  16. "log-server/model/common/request"
  17. "log-server/model/task"
  18. taskReq "log-server/model/task/request"
  19. "log-server/model/task/response"
  20. "log-server/utils"
  21. "mime/multipart"
  22. "path"
  23. "strconv"
  24. "strings"
  25. "time"
  26. )
  27. type TaskConfService struct {
  28. }
  29. //添加数据库记录
  30. func (e *TaskConfService) Upload(file response.UploadFileResponse) error {
  31. c := context.Background()
  32. key := fmt.Sprintf(SCRIPTDOWNLOADCHECK, file.TaskID)
  33. //添加redis缓存
  34. err := global.GVA_REDIS.Set(c, key, file.Md5String, 0).Err()
  35. if err != nil {
  36. global.GVA_LOG.Info("添加脚本md5值缓存失败:" + err.Error() + time.Now().Format("2006-01-02 15:04:05"))
  37. }
  38. return global.GVA_DB.Table("upload_file").Create(&file).Error
  39. }
  40. const ACCESSKEY string = "B81Gsvry2StqKVE3txS-7v9GBBfqykC9zhebmxnW"
  41. const SECRETKEY string = "YEZJuYcdeF7vRvzffxpopAVR-jMPZg9pZ-4IKTVW"
  42. const BUCKET string = "pinaishop"
  43. const SCRIPTDOWNLOADCHECK string = "script:%d"
  44. //更改的上传文件函数
  45. func (e *TaskConfService) UploadFileFunc(file *multipart.FileHeader, taskId string) (string, string, string, error) {
  46. // 读取文件后缀
  47. ext := path.Ext(file.Filename)
  48. // 读取文件名并加密
  49. name := strings.TrimSuffix(file.Filename, ext)
  50. name = utils.MD5V([]byte(name))
  51. // 拼接新文件名
  52. filename := name + "_" + time.Now().Format("20060102150405") + ext
  53. key := "shuyou/script/" + taskId + "/" + filename
  54. // 尝试创建此路径
  55. //mkdirErr := os.MkdirAll(global.GVA_CONFIG.Local.ScriptPath, os.ModePerm)
  56. //if mkdirErr != nil {
  57. // global.GVA_LOG.Error("function os.MkdirAll() Filed", zap.Any("err", mkdirErr.Error()))
  58. // return "", "", "", errors.New("function os.MkdirAll() Filed, err:" + mkdirErr.Error())
  59. //}
  60. // 拼接路径和文件名
  61. //p := global.GVA_CONFIG.Local.ScriptPath + "/" + filename
  62. //filepath := global.GVA_CONFIG.Local.ScriptPath + "/" + filename
  63. uploadErr := e.UploadFileToQiNiu(filename, taskId, file)
  64. if uploadErr != nil {
  65. global.GVA_LOG.Error("function UploadFileToQiNiu Filed", zap.Any("err", uploadErr.Error()))
  66. return "", "", "", errors.New("function UploadFileToQiNiu Filed, err:" + uploadErr.Error())
  67. }
  68. //f, openError := file.Open() // 读取文件
  69. f1, openErr := file.Open() // 读取文件生成MD5值
  70. if openErr != nil {
  71. global.GVA_LOG.Error("function file.Open() Filed", zap.Any("err", openErr.Error()))
  72. return "", "", "", errors.New("function file.Open() Filed, err:" + openErr.Error())
  73. }
  74. //defer f.Close() // 创建文件 defer 关闭
  75. defer f1.Close()
  76. //生成md5值
  77. md5h := md5.New()
  78. io.Copy(md5h, f1)
  79. md5String := hex.EncodeToString(md5h.Sum(nil))
  80. //
  81. //out, createErr := os.Create(p)
  82. //if createErr != nil {
  83. // global.GVA_LOG.Error("function os.Create() Filed", zap.Any("err", createErr.Error()))
  84. //
  85. // return "", "", "", errors.New("function os.Create() Filed, err:" + createErr.Error())
  86. //}
  87. //defer out.Close() // 创建文件 defer 关闭
  88. //_, copyErr := io.Copy(out, f) // 传输(拷贝)文件
  89. //fmt.Println("拷贝文件")
  90. //if copyErr != nil {
  91. // global.GVA_LOG.Error("function io.Copy() Filed", zap.Any("err", copyErr.Error()))
  92. // return "", "", "", errors.New("function io.Copy() Filed, err:" + copyErr.Error())
  93. //}
  94. return key, filename, md5String, nil
  95. }
  96. func (e *TaskConfService) UploadFileToQiNiu(fileName string, taskId string, file *multipart.FileHeader) error {
  97. accessKey := "B81Gsvry2StqKVE3txS-7v9GBBfqykC9zhebmxnW"
  98. secretKey := "YEZJuYcdeF7vRvzffxpopAVR-jMPZg9pZ-4IKTVW"
  99. mac := qbox.NewMac(accessKey, secretKey)
  100. bucket := "pinaishop"
  101. putPolicy := storage.PutPolicy{
  102. Scope: bucket,
  103. }
  104. key := "shuyou/script/" + taskId + "/" + fileName
  105. upToken := putPolicy.UploadToken(mac)
  106. cfg := storage.Config{}
  107. // 空间对应的机房
  108. cfg.Region = &storage.ZoneHuanan
  109. // 是否使用https域名
  110. cfg.UseHTTPS = true
  111. // 上传是否使用CDN上传加速
  112. cfg.UseCdnDomains = false
  113. formUploader := storage.NewFormUploader(&cfg)
  114. ret := storage.PutRet{}
  115. putExtra := storage.PutExtra{
  116. //Params: map[string]string{
  117. // "x:name": "github logo",
  118. //},
  119. }
  120. // Get the file size
  121. fileSize := file.Size
  122. f, openError := file.Open() // 读取文件
  123. if openError != nil {
  124. global.GVA_LOG.Error("function file.Open() Filed", zap.Any("err", openError.Error()))
  125. return errors.New("function file.Open() Filed, err:" + openError.Error())
  126. }
  127. defer f.Close()
  128. // Read the file into a byte slice
  129. bs := make([]byte, fileSize)
  130. _, err := bufio.NewReader(f).Read(bs)
  131. if err != nil && err != io.EOF {
  132. fmt.Println(err)
  133. return errors.New("文件转化成字节数组错误, err:" + err.Error())
  134. }
  135. err = formUploader.Put(context.Background(), &ret, upToken, key, bytes.NewReader(bs), fileSize, &putExtra)
  136. if err != nil {
  137. fmt.Println(err)
  138. return errors.New("上传七牛云错误, err:" + err.Error())
  139. }
  140. fmt.Println(ret.Key, ret.Hash)
  141. return nil
  142. }
  143. //上传文件
  144. func (e *TaskConfService) UploadFile(taskId int, user string, header *multipart.FileHeader) (file response.UploadFileResponse, err error) {
  145. //查询数据库记录数
  146. var count int64
  147. //获取最后一条记录
  148. var lastRecord response.UploadFileResponse
  149. var version int
  150. //定义下载前缀
  151. var prefix string = "http://cdn.pinaishop.kfzs.com/"
  152. global.GVA_DB.Table("upload_file").Where("task_id = ?", taskId).Count(&count)
  153. if count == 0 {
  154. version = 1
  155. } else {
  156. fmt.Println(count)
  157. global.GVA_DB.Table("upload_file").Where("task_id = ?", taskId).Order("id desc").Limit(1).Find(&lastRecord)
  158. fmt.Println(lastRecord)
  159. version = lastRecord.Version + 1
  160. recordArr := []response.UploadFileResponse{}
  161. global.GVA_DB.Table("upload_file").Where("task_id = ?", taskId).Find(&recordArr)
  162. fmt.Println(recordArr)
  163. }
  164. filePath, key, md5String, uploadErr := e.UploadFileFunc(header, strconv.Itoa(taskId))
  165. if uploadErr != nil {
  166. panic(err)
  167. }
  168. s := strings.Split(header.Filename, ".")
  169. f := response.UploadFileResponse{
  170. TaskID: taskId,
  171. ResponsiblePerson: user,
  172. Url: prefix + filePath,
  173. Name: header.Filename,
  174. Tag: s[len(s)-1],
  175. Key: key,
  176. Version: version,
  177. Md5String: md5String,
  178. State: 1,
  179. }
  180. return f, e.Upload(f)
  181. }
  182. //下载文件
  183. func (e *TaskConfService) DownloadFile(taskId int, md5String string) (info response.DownloadFile, err error) {
  184. var file response.UploadFileResponse
  185. //改由存储至数据库的时候拼接前缀
  186. //var prefix string = global.GVA_CONFIG.PrefixUrl.PrefixLocal
  187. //数据库中无记录,即不需要更新
  188. //err = global.GVA_DB.Table("upload_file").Where("task_id = ? and state = 1", taskId).Order("id desc").First(&file).Error
  189. //if errors.Is(err, gorm.ErrRecordNotFound) {
  190. // info = response.DownloadFile{
  191. // Url: "",
  192. // Md5String: "",
  193. // Flag: false,
  194. // }
  195. // return info, errors.New("无对应脚本")
  196. //}
  197. //
  198. //if file.Md5String == md5String {
  199. // info = response.DownloadFile{
  200. // Url: "",
  201. // Md5String: "",
  202. // Flag: false,
  203. // }
  204. // return info, errors.New("不需要更新")
  205. //} else {
  206. // fullUrl := file.Url
  207. // info = response.DownloadFile{
  208. // Url: fullUrl,
  209. // Md5String: file.Md5String,
  210. // Flag: true,
  211. // }
  212. //}
  213. //先对比缓存中的md5string,如果缓存中没有,返回无对应脚本;如果缓存中md5一致,则返回不需要更新
  214. //最后更新的时候再查询数据库
  215. c := context.Background()
  216. key := fmt.Sprintf(SCRIPTDOWNLOADCHECK, taskId)
  217. existMd5, err := global.GVA_REDIS.Get(c, key).Result()
  218. if err != nil {
  219. //不存在脚本
  220. return info, errors.New("无对应脚本")
  221. }
  222. if existMd5 == "无数据" {
  223. //脚本不存在
  224. return info, errors.New("脚本不存在")
  225. }
  226. if existMd5 == md5String {
  227. //不需要更新
  228. return info, errors.New("不需要更新")
  229. }
  230. err = global.GVA_DB.Table("upload_file").Where("task_id = ? and state = 1", taskId).Order("id desc").First(&file).Error
  231. if err != nil {
  232. return info, err
  233. } else {
  234. fullUrl := file.Url
  235. info = response.DownloadFile{
  236. Url: fullUrl,
  237. Md5String: file.Md5String,
  238. Flag: true,
  239. }
  240. }
  241. //将查找出来的md5值重新加回去
  242. err = global.GVA_REDIS.Set(c, key, file.Md5String, 0).Err()
  243. if err != nil {
  244. global.GVA_LOG.Info("添加脚本md5值缓存失败:" + err.Error() + time.Now().Format("2006-01-02 15:04:05"))
  245. }
  246. return info, err
  247. }
  248. //条件查询脚本列表
  249. func (e *TaskConfService) GetScriptList(script task.GameScriptResponse, info request.PageInfo, order string, desc bool) (list interface{}, total int64, err error) {
  250. //获取分页数据
  251. limit := info.PageSize
  252. offset := (info.Page - 1) * info.PageSize
  253. //绑定操作结构体
  254. db := global.GVA_DB.Table("upload_file").Model(&task.GameScriptResponse{})
  255. var scriptList []task.GameScriptResponse
  256. //条件查询
  257. if script.ResponsiblePerson != "" {
  258. db = db.Where("responsible_person = ?", script.ResponsiblePerson)
  259. }
  260. if script.TaskID != 0 {
  261. db = db.Where("task_id = ?", script.TaskID)
  262. }
  263. //先过滤在排序
  264. if err = db.Count(&total).Error; err != nil {
  265. return scriptList, total, err
  266. } else {
  267. //分页
  268. db.Limit(limit).Offset(offset)
  269. //判断是否有排序字段
  270. if order != "" {
  271. var orderStr string
  272. orderMap := make(map[string]bool, 1)
  273. orderMap["create_time"] = true
  274. orderMap["task_id"] = true
  275. orderMap["name"] = true
  276. orderMap["responsible_person"] = true
  277. orderMap["version"] = true
  278. if orderMap[order] {
  279. //合法排序字符
  280. if desc {
  281. orderStr = order + " desc"
  282. } else {
  283. orderStr = order
  284. }
  285. } else {
  286. //传入排序字段非法
  287. err = fmt.Errorf("传入非法字段 %v", order)
  288. return scriptList, total, err
  289. }
  290. err = db.Order(orderStr).Find(&scriptList).Error
  291. } else {
  292. //默认按照名字升序排序
  293. err = db.Order("id desc").Find(&scriptList).Error
  294. }
  295. }
  296. return scriptList, total, err
  297. }
  298. //更改脚本状态
  299. func (e *TaskConfService) UpdateScriptStatus(c taskReq.UpdateScriptStatusRequest) (err error) {
  300. var entity response.UploadFileResponse
  301. err = global.GVA_DB.Table("upload_file").Where("id = ?", c.Id).First(&entity).Error
  302. if errors.Is(err, gorm.ErrRecordNotFound) {
  303. return errors.New("请传入正确的Id")
  304. }
  305. //更新数据库记录
  306. err = global.GVA_DB.Table("upload_file").Where("id = ?", c.Id).Update("state", c.State).Error
  307. //更新缓存状态
  308. err1 := e.UpdateRedisCache(entity.TaskID)
  309. if err1 != nil {
  310. global.GVA_LOG.Info("更新脚本缓存失败:" + err1.Error() + time.Now().Format("2006-01-02 15:04:05"))
  311. }
  312. return err
  313. }
  314. //更改推送标准
  315. func (e *TaskConfService) JudgeOperate(taskConf task.TaskConf) (err error) {
  316. //查找数据库中是否有这条记录
  317. var entity task.TaskConf
  318. err = global.GVA_DB.Model(&task.TaskConf{}).Where("task_id = ?", taskConf.TaskId).First(&entity).Error
  319. //如果没有,创建
  320. if errors.Is(err, gorm.ErrRecordNotFound) {
  321. return global.GVA_DB.Model(&task.TaskConf{}).Create(&taskConf).Error
  322. }
  323. //如果有,更新
  324. return global.GVA_DB.Model(&task.TaskConf{}).Where("task_id = ?", taskConf.TaskId).Omit("task_id", "user").Updates(map[string]interface{}{"add_fee_notice": taskConf.AddFeeNotice, "simulator_type": taskConf.SimulatorType, "push_pay_ratio": taskConf.PushPayRatio}).Error
  325. }
  326. //删除上传脚本
  327. func (e *TaskConfService) DeleteScript(file task.GameScriptResponse) (err error) {
  328. //七牛云删除所需要的条件
  329. mac := qbox.NewMac(ACCESSKEY, SECRETKEY)
  330. cfg := storage.Config{
  331. // 是否使用https域名进行资源管理
  332. UseHTTPS: true,
  333. }
  334. // 指定空间所在的区域,如果不指定将自动探测
  335. // 如果没有特殊需求,默认不需要指定
  336. //cfg.Region=&storage.ZoneHuabei
  337. bucketManager := storage.NewBucketManager(mac, &cfg)
  338. //删除数据库记录
  339. var entity task.GameScriptResponse
  340. err = global.GVA_DB.Table("upload_file").Where("id", file.Id).First(&entity).Error
  341. if errors.Is(err, gorm.ErrRecordNotFound) {
  342. return errors.New("无此条脚本记录")
  343. }
  344. key := file.Url[30:]
  345. fmt.Println(key)
  346. err = global.GVA_DB.Table("upload_file").Delete(&entity).Error
  347. if err != nil {
  348. return err
  349. }
  350. //更新缓存状态
  351. err = e.UpdateRedisCache(entity.TaskID)
  352. if err != nil {
  353. global.GVA_LOG.Info("更新脚本缓存失败:" + err.Error() + time.Now().Format("2006-01-02 15:04:05"))
  354. }
  355. //删除七牛云的记录
  356. //删除七牛云之前先做判断
  357. if key == "" {
  358. return errors.New("请传入正确的key!")
  359. }
  360. if key[:13] != "shuyou/script" {
  361. return errors.New("请传入正确的key!")
  362. }
  363. err = bucketManager.Delete(BUCKET, key)
  364. fmt.Println(err)
  365. return err
  366. }
  367. //批量删除脚本
  368. func (e *TaskConfService) BulkDeleteScript(ids []int) (err error) {
  369. var total int64
  370. var scriptList []task.GameScriptResponse
  371. taskIdMap := make(map[int]int)
  372. db := global.GVA_DB.Table("upload_file").Where("id in ?", ids)
  373. err = db.Count(&total).Error
  374. if err != nil {
  375. return err
  376. }
  377. err = db.Find(&scriptList).Error
  378. if err != nil {
  379. return
  380. }
  381. keys := make([]string, len(scriptList))
  382. //获取key数组 及task_id的map
  383. for k, _ := range scriptList {
  384. fmt.Println(scriptList[k].Url[30:])
  385. keys[k] = scriptList[k].Url[30:]
  386. if taskIdMap[scriptList[k].TaskID] != 0 {
  387. taskIdMap[scriptList[k].TaskID]++
  388. } else {
  389. taskIdMap[scriptList[k].TaskID] = 1
  390. }
  391. }
  392. fmt.Println(keys)
  393. //批量删除脚本数据库记录
  394. err = global.GVA_DB.Model(&task.GameScriptResponse{}).Delete("id in ?", ids).Error
  395. if err != nil {
  396. return err
  397. }
  398. //遍历taskIdMap 更新缓存状态
  399. for k, _ := range taskIdMap {
  400. err := e.UpdateRedisCache(k)
  401. if err != nil {
  402. global.GVA_LOG.Info("更新脚本md5值缓存失败:" + err.Error() + time.Now().Format("2006-01-02 15:04:05"))
  403. return err
  404. }
  405. }
  406. return
  407. //批量删除七牛云脚本记录
  408. }
  409. //更新缓存状态
  410. func (e *TaskConfService) UpdateRedisCache(taskId int) (err error) {
  411. var file response.UploadFileResponse
  412. contexts := context.Background()
  413. //查找合格的file
  414. key := fmt.Sprintf(SCRIPTDOWNLOADCHECK, taskId)
  415. err = global.GVA_DB.Table("upload_file").Where("task_id = ? and state = 1", taskId).Order("id desc").First(&file).Error
  416. if errors.Is(err, gorm.ErrRecordNotFound) {
  417. //已无符合条件脚本
  418. //删除redis缓存,并且打印日志说明
  419. fmt.Println("无可用脚本,尝试删除")
  420. err := global.GVA_REDIS.Set(contexts, key, "无数据", time.Second*1).Err()
  421. if err != nil {
  422. global.GVA_LOG.Info("删除脚本md5值缓存失败:" + err.Error() + time.Now().Format("2006-01-02 15:04:05"))
  423. return err
  424. }
  425. } else {
  426. //找到了数据库记录,更新缓存
  427. fmt.Println("更新缓存记录")
  428. err := global.GVA_REDIS.Set(contexts, key, file.Md5String, 0).Err()
  429. if err != nil {
  430. global.GVA_LOG.Info("更新脚本md5值缓存失败:" + err.Error() + time.Now().Format("2006-01-02 15:04:05"))
  431. return err
  432. }
  433. }
  434. return err
  435. }
  436. func (e *TaskConfService) BulkDeleteQiNiuYunScript(keys []string) (err error) {
  437. //七牛云删除所需要的条件
  438. mac := qbox.NewMac(ACCESSKEY, SECRETKEY)
  439. cfg := storage.Config{
  440. // 是否使用https域名进行资源管理
  441. UseHTTPS: true,
  442. }
  443. // 指定空间所在的区域,如果不指定将自动探测
  444. // 如果没有特殊需求,默认不需要指定
  445. //cfg.Region=&storage.ZoneHuabei
  446. bucketManager := storage.NewBucketManager(mac, &cfg)
  447. //每个batch的操作数量不可以超过1000个,如果总数量超过1000,需要分批发送
  448. bucket := BUCKET
  449. //验证keys安全性
  450. for _, v := range keys {
  451. //删除七牛云之前先做判断
  452. if v == "" {
  453. return errors.New("请传入正确的key!")
  454. }
  455. if v[:13] != "shuyou/script" {
  456. return errors.New("请传入正确的key!")
  457. }
  458. }
  459. deleteOps := make([]string, 0, len(keys))
  460. for _, key := range keys {
  461. deleteOps = append(deleteOps, storage.URIDelete(bucket, key))
  462. }
  463. rets, err := bucketManager.Batch(deleteOps)
  464. if len(rets) == 0 {
  465. // 处理错误
  466. if e, ok := err.(*storage.ErrorInfo); ok {
  467. fmt.Printf("batch error, code:%s", e.Code)
  468. } else {
  469. fmt.Printf("batch error, %s", err)
  470. }
  471. return
  472. }
  473. // 返回 rets,先判断 rets 是否
  474. for _, ret := range rets {
  475. // 200 为成功
  476. if ret.Code == 200 {
  477. fmt.Printf("%d\n", ret.Code)
  478. } else {
  479. err = errors.New(ret.Data.Error)
  480. fmt.Printf("%s\n", ret.Data.Error)
  481. }
  482. }
  483. return err
  484. }