This commit is contained in:
withchao
2023-03-29 10:15:21 +08:00
parent ff65eeddba
commit 8ec04f46b0
7 changed files with 252 additions and 211 deletions
+34 -30
View File
@@ -113,19 +113,19 @@ func (c *s3Database) ApplyPut(ctx context.Context, req *third.ApplyPutReq) (*thi
if err := c.obj.CheckName(req.Name); err != nil {
return nil, err
}
if req.CleanTime != 0 && req.CleanTime <= time.Now().UnixMilli() {
return nil, errors.New("invalid CleanTime")
if req.ValidTime != 0 && req.ValidTime <= time.Now().UnixMilli() {
return nil, errors.New("invalid ValidTime")
}
var expirationTime *time.Time
if req.CleanTime != 0 {
expirationTime = utils.ToPtr(time.UnixMilli(req.CleanTime))
if req.ValidTime != 0 {
expirationTime = utils.ToPtr(time.UnixMilli(req.ValidTime))
}
if hash, err := c.hash.Take(ctx, req.Hash, c.obj.Name()); err == nil {
o := relation.ObjectInfoModel{
Name: req.Name,
Hash: hash.Hash,
ExpirationTime: expirationTime,
CreateTime: time.Now(),
Name: req.Name,
Hash: hash.Hash,
ValidTime: expirationTime,
CreateTime: time.Now(),
}
if err := c.info.SetObject(ctx, &o); err != nil {
return nil, err
@@ -139,13 +139,14 @@ func (c *s3Database) ApplyPut(ctx context.Context, req *third.ApplyPutReq) (*thi
const effective = time.Hour * 24 * 2
req.FragmentSize, pack = c.getFragmentNum(req.FragmentSize, req.Size)
put := relation.ObjectPutModel{
PutID: c.UUID(),
Hash: req.Hash,
Name: req.Name,
ObjectSize: req.Size,
FragmentSize: req.FragmentSize,
ExpirationTime: expirationTime,
EffectiveTime: time.Now().Add(effective),
PutID: c.UUID(),
Hash: req.Hash,
Name: req.Name,
ObjectSize: req.Size,
ContentType: req.ContentType,
FragmentSize: req.FragmentSize,
ValidTime: expirationTime,
EffectiveTime: time.Now().Add(effective),
}
put.Path = path.Join(tempPrefix, c.today(), req.Hash, put.PutID)
putURLs := make([]string, 0, pack)
@@ -197,9 +198,9 @@ func (c *s3Database) GetPut(ctx context.Context, req *third.GetPutReq) (*third.G
}
fragments[i] = &third.GetPutFragment{Size: o.Size, Hash: o.Hash}
}
var cleanTime int64
if up.ExpirationTime != nil {
cleanTime = up.ExpirationTime.UnixMilli()
var validTime int64
if up.ValidTime != nil {
validTime = up.ValidTime.UnixMilli()
}
return &third.GetPutResp{
FragmentSize: up.FragmentSize,
@@ -207,7 +208,8 @@ func (c *s3Database) GetPut(ctx context.Context, req *third.GetPutReq) (*third.G
Name: up.Name,
Hash: up.Hash,
Fragments: fragments,
CleanTime: cleanTime,
ContentType: up.ContentType,
ValidTime: validTime,
}, nil
}
@@ -233,15 +235,15 @@ func (c *s3Database) ConfirmPut(ctx context.Context, req *third.ConfirmPutReq) (
if put.EffectiveTime.UnixMilli() < now {
return nil, errors.New("upload expired")
}
if put.ExpirationTime != nil && put.ExpirationTime.UnixMilli() < now {
if put.ValidTime != nil && put.ValidTime.UnixMilli() < now {
return nil, errors.New("object expired")
}
if hash, err := c.hash.Take(ctx, put.Hash, c.obj.Name()); err == nil {
o := relation.ObjectInfoModel{
Name: put.Name,
Hash: hash.Hash,
ExpirationTime: put.ExpirationTime,
CreateTime: time.Now(),
Name: put.Name,
Hash: hash.Hash,
ValidTime: put.ValidTime,
CreateTime: time.Now(),
}
if err := c.info.SetObject(ctx, &o); err != nil {
return nil, err
@@ -346,10 +348,11 @@ func (c *s3Database) ConfirmPut(ctx context.Context, req *third.ConfirmPutReq) (
return nil, err
}
o := &relation.ObjectInfoModel{
Name: put.Name,
Hash: put.Hash,
ExpirationTime: put.ExpirationTime,
CreateTime: time.Now(),
Name: put.Name,
Hash: put.Hash,
ContentType: put.ContentType,
ValidTime: put.ValidTime,
CreateTime: time.Now(),
}
if err := c.info.SetObject(ctx, o); err != nil {
return nil, err
@@ -367,14 +370,15 @@ func (c *s3Database) GetUrl(ctx context.Context, req *third.GetUrlReq) (*third.G
if err != nil {
return nil, err
}
if info.ExpirationTime != nil && info.ExpirationTime.Before(time.Now()) {
if info.ValidTime != nil && info.ValidTime.Before(time.Now()) {
return nil, errs.ErrRecordNotFound.Wrap("object expired")
}
hash, err := c.hash.Take(ctx, info.Hash, c.obj.Name())
if err != nil {
return nil, err
}
u, err := c.obj.GetURL(ctx, hash.Bucket, hash.Name, time.Duration(req.Expires)*time.Millisecond)
opt := obj.HeaderOption{Filename: info.Name, ContentType: info.ContentType}
u, err := c.obj.PresignedGetURL(ctx, hash.Bucket, hash.Name, time.Duration(req.Expires)*time.Millisecond, &opt)
if err != nil {
return nil, err
}
+15 -4
View File
@@ -9,6 +9,7 @@ import (
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
"github.com/minio/minio-go/v7/pkg/s3utils"
"net/http"
"net/url"
"time"
)
@@ -85,8 +86,18 @@ func (m *minioImpl) DataBucket() string {
return m.dataBucket
}
func (m *minioImpl) GetURL(ctx context.Context, bucket string, name string, expires time.Duration) (string, error) {
u, err := m.client.PresignedGetObject(ctx, bucket, name, expires, nil)
func (m *minioImpl) PresignedGetURL(ctx context.Context, bucket string, name string, expires time.Duration, opt *HeaderOption) (string, error) {
var reqParams url.Values
if opt != nil {
reqParams = make(url.Values)
if opt.ContentType != "" {
reqParams.Set("response-content-type", opt.ContentType)
}
if opt.Filename != "" {
reqParams.Set("response-content-disposition", "attachment;filename="+opt.Filename)
}
}
u, err := m.client.PresignedGetObject(ctx, bucket, name, expires, reqParams)
if err != nil {
return "", err
}
@@ -177,9 +188,9 @@ func (m *minioImpl) IsNotFound(err error) bool {
}
switch e := err.(type) {
case minio.ErrorResponse:
return e.StatusCode == 404 && e.Code == "NoSuchKey"
return e.StatusCode == http.StatusNotFound || e.Code == "NoSuchKey"
case *minio.ErrorResponse:
return e.StatusCode == 404 && e.Code == "NoSuchKey"
return e.StatusCode == http.StatusNotFound || e.Code == "NoSuchKey"
default:
return false
}
+7 -3
View File
@@ -19,6 +19,11 @@ type ApplyPutArgs struct {
MaxObjectSize int64
}
type HeaderOption struct {
ContentType string
Filename string
}
type ObjectInfo struct {
Size int64
Hash string
@@ -37,9 +42,8 @@ type Interface interface {
TempBucket() string
// DataBucket 永久存储的桶名
DataBucket() string
// GetURL 通过桶名和对象名返回URL
//GetURL(bucket string, name string) string
GetURL(ctx context.Context, bucket string, name string, expires time.Duration) (string, error)
// PresignedGetURL 通过桶名和对象名返回URL
PresignedGetURL(ctx context.Context, bucket string, name string, expires time.Duration, opt *HeaderOption) (string, error)
// PresignedPutURL 申请上传,返回PUT的上传地址
PresignedPutURL(ctx context.Context, args *ApplyPutArgs) (string, error)
// GetObjectInfo 获取对象信息
+5 -4
View File
@@ -10,10 +10,11 @@ const (
)
type ObjectInfoModel struct {
Name string `gorm:"column:name;primary_key"`
Hash string `gorm:"column:hash"`
ExpirationTime *time.Time `gorm:"column:expiration_time"`
CreateTime time.Time `gorm:"column:create_time"`
Name string `gorm:"column:name;primary_key"`
Hash string `gorm:"column:hash"`
ContentType string `gorm:"column:content_type"`
ValidTime *time.Time `gorm:"column:valid_time"`
CreateTime time.Time `gorm:"column:create_time"`
}
func (ObjectInfoModel) TableName() string {
+11 -10
View File
@@ -10,16 +10,17 @@ const (
)
type ObjectPutModel struct {
PutID string `gorm:"column:put_id;primary_key"`
Hash string `gorm:"column:hash"`
Path string `gorm:"column:path"`
Name string `gorm:"column:name"`
ObjectSize int64 `gorm:"column:object_size"`
FragmentSize int64 `gorm:"column:fragment_size"`
Complete bool `gorm:"column:complete"`
ExpirationTime *time.Time `gorm:"column:expiration_time"`
EffectiveTime time.Time `gorm:"column:effective_time"`
CreateTime time.Time `gorm:"column:create_time"`
PutID string `gorm:"column:put_id;primary_key"`
Hash string `gorm:"column:hash"`
Path string `gorm:"column:path"`
Name string `gorm:"column:name"`
ContentType string `gorm:"column:content_type"`
ObjectSize int64 `gorm:"column:object_size"`
FragmentSize int64 `gorm:"column:fragment_size"`
Complete bool `gorm:"column:complete"`
ValidTime *time.Time `gorm:"column:valid_time"`
EffectiveTime time.Time `gorm:"column:effective_time"`
CreateTime time.Time `gorm:"column:create_time"`
}
func (ObjectPutModel) TableName() string {