131 lines
3.0 KiB
Go
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())
|
|
|
|
}
|