upload.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package v1
  2. import (
  3. "bytes"
  4. "context"
  5. "crypto/hmac"
  6. "crypto/sha1"
  7. "encoding/base64"
  8. "fmt"
  9. "io"
  10. "net/url"
  11. "strings"
  12. "time"
  13. v1pb "go-common/app/admin/live/live-admin/api/http/v1"
  14. "go-common/app/admin/live/live-admin/conf"
  15. "go-common/app/admin/live/live-admin/dao"
  16. "go-common/app/admin/live/live-admin/model"
  17. "go-common/library/database/bfs"
  18. "go-common/library/ecode"
  19. "go-common/library/log"
  20. "go-common/library/net/http/blademaster"
  21. )
  22. // UploadService struct
  23. type UploadService struct {
  24. conf *conf.Config
  25. // optionally add other properties here, such as dao
  26. dao *dao.Dao
  27. }
  28. //NewUploadService init
  29. func NewUploadService(c *conf.Config, d *dao.Dao) (s *UploadService) {
  30. s = &UploadService{
  31. conf: c,
  32. dao: d,
  33. }
  34. return s
  35. }
  36. // File implementation
  37. // `method:"POST" content-type:"multipart/form-data" midware:"guest"`
  38. func (s *UploadService) File(ctx context.Context, req *v1pb.UploadFileReq) (resp *v1pb.UploadFileResp, err error) {
  39. _, ok := s.conf.Bucket[req.Bucket]
  40. if !ok {
  41. err = ecode.UploadBucketErr
  42. return
  43. }
  44. if !s.verify(ctx, req.Token) {
  45. err = ecode.Error(ecode.InvalidParam, "invalid upload token")
  46. return
  47. }
  48. bmc := ctx.(*blademaster.Context)
  49. file, _, err := bmc.Request.FormFile("file_up")
  50. if err != nil {
  51. log.Error("Parse file part failure: %v", err)
  52. err = ecode.Error(ecode.InvalidParam, "file not found")
  53. return
  54. }
  55. defer file.Close()
  56. fileData := new(bytes.Buffer)
  57. if _, err = io.Copy(fileData, file); err != nil {
  58. log.Error("Read file data failure: %v", err)
  59. err = ecode.UploadUploadErr
  60. return
  61. }
  62. resp = &v1pb.UploadFileResp{}
  63. bfsClient := bfs.New(nil)
  64. bfsReq := &bfs.Request{
  65. Bucket: req.Bucket,
  66. Dir: req.Dir,
  67. ContentType: req.ContentType,
  68. Filename: req.Filename,
  69. File: fileData.Bytes(),
  70. WMKey: req.WmKey,
  71. WMText: req.WmText,
  72. WMPaddingX: req.WmPaddingX,
  73. WMPaddingY: req.WmPaddingY,
  74. WMScale: req.WmScale,
  75. }
  76. model.TweakWatermark(bfsReq)
  77. resp.Url, err = bfsClient.Upload(ctx, bfsReq)
  78. if err != nil {
  79. log.Error("Upload to bfs failure: %v", err)
  80. err = ecode.UploadUploadErr
  81. return
  82. }
  83. resp.Url = s.getPrivateURL(req.Bucket, resp.Url)
  84. return
  85. }
  86. func (s *UploadService) verify(ctx context.Context, token string) bool {
  87. return s.dao.VerifyUploadToken(ctx, token)
  88. }
  89. func (s *UploadService) getPrivateURL(bucket, fileURL string) string {
  90. bucketConf, ok := s.conf.Bucket[bucket]
  91. if !ok || !bucketConf.Private {
  92. return fileURL
  93. }
  94. bucketFindStr := fmt.Sprintf("/%s/", bucket)
  95. bucketIndex := strings.Index(fileURL, bucketFindStr)
  96. if bucketIndex < 0 {
  97. return fileURL
  98. }
  99. filename := fileURL[bucketIndex+len(bucketFindStr):]
  100. now := time.Now().Unix()
  101. mac := hmac.New(sha1.New, []byte(bucketConf.Secret))
  102. salt := fmt.Sprintf("GET\n%s\n%s\n%d\n", bucket, filename, now)
  103. mac.Write([]byte(salt))
  104. sign := base64.StdEncoding.EncodeToString(mac.Sum(nil))
  105. token := fmt.Sprintf("%s:%s:%d", bucketConf.Key, sign, now)
  106. v := url.Values{}
  107. v.Set("token", token)
  108. return fmt.Sprintf("%s?%s", fileURL, v.Encode())
  109. }