123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- package v1
- import (
- "bytes"
- "context"
- "crypto/hmac"
- "crypto/sha1"
- "encoding/base64"
- "fmt"
- "io"
- "net/url"
- "strings"
- "time"
- v1pb "go-common/app/admin/live/live-admin/api/http/v1"
- "go-common/app/admin/live/live-admin/conf"
- "go-common/app/admin/live/live-admin/dao"
- "go-common/app/admin/live/live-admin/model"
- "go-common/library/database/bfs"
- "go-common/library/ecode"
- "go-common/library/log"
- "go-common/library/net/http/blademaster"
- )
- // UploadService struct
- type UploadService struct {
- conf *conf.Config
- // optionally add other properties here, such as dao
- dao *dao.Dao
- }
- //NewUploadService init
- func NewUploadService(c *conf.Config, d *dao.Dao) (s *UploadService) {
- s = &UploadService{
- conf: c,
- dao: d,
- }
- return s
- }
- // File implementation
- // `method:"POST" content-type:"multipart/form-data" midware:"guest"`
- func (s *UploadService) File(ctx context.Context, req *v1pb.UploadFileReq) (resp *v1pb.UploadFileResp, err error) {
- _, ok := s.conf.Bucket[req.Bucket]
- if !ok {
- err = ecode.UploadBucketErr
- return
- }
- if !s.verify(ctx, req.Token) {
- err = ecode.Error(ecode.InvalidParam, "invalid upload token")
- return
- }
- bmc := ctx.(*blademaster.Context)
- file, _, err := bmc.Request.FormFile("file_up")
- if err != nil {
- log.Error("Parse file part failure: %v", err)
- err = ecode.Error(ecode.InvalidParam, "file not found")
- return
- }
- defer file.Close()
- fileData := new(bytes.Buffer)
- if _, err = io.Copy(fileData, file); err != nil {
- log.Error("Read file data failure: %v", err)
- err = ecode.UploadUploadErr
- return
- }
- resp = &v1pb.UploadFileResp{}
- bfsClient := bfs.New(nil)
- bfsReq := &bfs.Request{
- Bucket: req.Bucket,
- Dir: req.Dir,
- ContentType: req.ContentType,
- Filename: req.Filename,
- File: fileData.Bytes(),
- WMKey: req.WmKey,
- WMText: req.WmText,
- WMPaddingX: req.WmPaddingX,
- WMPaddingY: req.WmPaddingY,
- WMScale: req.WmScale,
- }
- model.TweakWatermark(bfsReq)
- resp.Url, err = bfsClient.Upload(ctx, bfsReq)
- if err != nil {
- log.Error("Upload to bfs failure: %v", err)
- err = ecode.UploadUploadErr
- return
- }
- resp.Url = s.getPrivateURL(req.Bucket, resp.Url)
- return
- }
- func (s *UploadService) verify(ctx context.Context, token string) bool {
- return s.dao.VerifyUploadToken(ctx, token)
- }
- func (s *UploadService) getPrivateURL(bucket, fileURL string) string {
- bucketConf, ok := s.conf.Bucket[bucket]
- if !ok || !bucketConf.Private {
- return fileURL
- }
- bucketFindStr := fmt.Sprintf("/%s/", bucket)
- bucketIndex := strings.Index(fileURL, bucketFindStr)
- if bucketIndex < 0 {
- return fileURL
- }
- filename := fileURL[bucketIndex+len(bucketFindStr):]
- now := time.Now().Unix()
- mac := hmac.New(sha1.New, []byte(bucketConf.Secret))
- salt := fmt.Sprintf("GET\n%s\n%s\n%d\n", bucket, filename, now)
- mac.Write([]byte(salt))
- sign := base64.StdEncoding.EncodeToString(mac.Sum(nil))
- token := fmt.Sprintf("%s:%s:%d", bucketConf.Key, sign, now)
- v := url.Values{}
- v.Set("token", token)
- return fmt.Sprintf("%s?%s", fileURL, v.Encode())
- }
|