go-common/app/admin/live/live-admin/service/v1/upload.go
2019-04-22 18:49:16 +08:00

131 lines
3.0 KiB
Go

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())
}