You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
3.0 KiB
130 lines
3.0 KiB
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()) |
|
|
|
}
|
|
|