Compare commits
No commits in common. "23138f4e06222f96664482b27bcd523a640d7f4d" and "1722fa82f87e970ed1a4040c54d6d2dcd78ce6b7" have entirely different histories.
23138f4e06
...
1722fa82f8
@ -5,14 +5,9 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gitea.bvbej.com/bvbej/base-golang/pkg/md5"
|
||||
"github.com/qiniu/go-sdk/v7/auth"
|
||||
"github.com/qiniu/go-sdk/v7/cdn"
|
||||
"github.com/qiniu/go-sdk/v7/storagev2/credentials"
|
||||
"github.com/qiniu/go-sdk/v7/storagev2/downloader"
|
||||
"github.com/qiniu/go-sdk/v7/storagev2/http_client"
|
||||
"github.com/qiniu/go-sdk/v7/storagev2/objects"
|
||||
"github.com/qiniu/go-sdk/v7/storagev2/uploader"
|
||||
"github.com/qiniu/go-sdk/v7/storagev2/uptoken"
|
||||
"gitea.bvbej.com/bvbej/base-golang/tool"
|
||||
"github.com/qiniu/go-sdk/v7/auth/qbox"
|
||||
"github.com/qiniu/go-sdk/v7/storage"
|
||||
"github.com/tidwall/gjson"
|
||||
"io"
|
||||
"net/http"
|
||||
@ -22,37 +17,33 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Qhash string
|
||||
|
||||
const (
|
||||
QSha1 Qhash = "sha1"
|
||||
QSha256 Qhash = "sha256"
|
||||
)
|
||||
|
||||
var _ QiNiu = (*qiNiu)(nil)
|
||||
|
||||
type QiNiu interface {
|
||||
SetDefaultUploadTokenTTL(duration time.Duration)
|
||||
GetUploadToken() (string, error)
|
||||
GetCallbackUploadToken(callbackURL string) (string, error)
|
||||
TimestampSecuritySign(urlStr string, ttl time.Duration) (string, error)
|
||||
UploadFile(key, localFile, callbackURL string) (*PutRet, error)
|
||||
GetPrivateURL(key string, ttl time.Duration) (string, error)
|
||||
i()
|
||||
SetDefaultUploadTokenTTL(ttl uint64)
|
||||
GetCallbackUploadToken(ttl uint64, callbackURL string) string
|
||||
GetUploadToken(ttl uint64) string
|
||||
GetPrivateURL(key string, ttl uint64) string
|
||||
VerifyCallback(req *http.Request) (bool, error)
|
||||
GetFileInfo(key string) (*objects.ObjectDetails, error)
|
||||
UploadFile(key, localFile string) (*PutRet, error)
|
||||
ResumeUploadFile(key, localFile string) (*PutRet, error)
|
||||
DelFile(key string) error
|
||||
ListFiles(keyPrefix, marker string, limit uint64) ([]objects.ObjectDetails, error)
|
||||
GetFileHash(path string, qhash Qhash) (hash string, err error)
|
||||
TimestampSecuritySign(path string, ttl time.Duration) string
|
||||
GetFileInfo(key string) *storage.FileInfo
|
||||
ListFiles(prefix, delimiter, marker string, limit int) (entries []storage.ListItem, commonPrefixes []string, nextMarker string, hasNext bool, err error)
|
||||
GetFileHash(path, qhash string) (hash string, err error)
|
||||
}
|
||||
|
||||
type qiNiu struct {
|
||||
mac *qbox.Mac
|
||||
bucketManager *storage.BucketManager
|
||||
conf *storage.Config
|
||||
bucket string
|
||||
domain string
|
||||
securityKey string
|
||||
credentials *auth.Credentials
|
||||
bucketManager *objects.Bucket
|
||||
md5 md5.MD5
|
||||
uploadTokenTTL time.Duration
|
||||
uploadTokenTTL uint64
|
||||
}
|
||||
|
||||
type PutRet struct {
|
||||
@ -66,75 +57,78 @@ type PutRet struct {
|
||||
}
|
||||
|
||||
func New(accessKey, secretKey, bucket, domain, securityKey string) QiNiu {
|
||||
cred := credentials.NewCredentials(accessKey, secretKey)
|
||||
objectsManager := objects.NewObjectsManager(&objects.ObjectsManagerOptions{
|
||||
Options: http_client.Options{Credentials: cred},
|
||||
})
|
||||
mac := qbox.NewMac(accessKey, secretKey)
|
||||
conf := &storage.Config{
|
||||
UseHTTPS: true, //是否使用https域名
|
||||
UseCdnDomains: false, //上传是否使用CDN上传加速
|
||||
}
|
||||
return &qiNiu{
|
||||
mac: mac,
|
||||
bucketManager: storage.NewBucketManager(mac, conf),
|
||||
bucket: bucket,
|
||||
domain: domain,
|
||||
securityKey: securityKey,
|
||||
credentials: cred,
|
||||
bucketManager: objectsManager.Bucket(bucket),
|
||||
conf: conf,
|
||||
md5: md5.New(),
|
||||
uploadTokenTTL: time.Second * 3600,
|
||||
uploadTokenTTL: 3600,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *qiNiu) SetDefaultUploadTokenTTL(duration time.Duration) {
|
||||
q.uploadTokenTTL = duration
|
||||
func (q *qiNiu) i() {}
|
||||
|
||||
func (q *qiNiu) SetDefaultUploadTokenTTL(ttl uint64) {
|
||||
q.uploadTokenTTL = ttl
|
||||
}
|
||||
|
||||
func (q *qiNiu) GetUploadToken() (string, error) {
|
||||
putPolicy, err := uptoken.NewPutPolicy(q.bucket, time.Now().Add(q.uploadTokenTTL))
|
||||
if err != nil {
|
||||
return "", err
|
||||
func (q *qiNiu) GetUploadToken(ttl uint64) string {
|
||||
putPolicy := storage.PutPolicy{
|
||||
Scope: q.bucket,
|
||||
Expires: ttl,
|
||||
}
|
||||
return uptoken.NewSigner(putPolicy, q.credentials).GetUpToken(context.Background())
|
||||
return putPolicy.UploadToken(q.mac)
|
||||
}
|
||||
|
||||
func (q *qiNiu) GetCallbackUploadToken(callbackURL string) (string, error) {
|
||||
putPolicy, err := uptoken.NewPutPolicy(q.bucket, time.Now().Add(q.uploadTokenTTL))
|
||||
if err != nil {
|
||||
return "", err
|
||||
func (q *qiNiu) GetCallbackUploadToken(ttl uint64, callbackURL string) string {
|
||||
putPolicy := storage.PutPolicy{
|
||||
Scope: q.bucket,
|
||||
CallbackURL: callbackURL,
|
||||
CallbackBody: `{"key":"$(key)","hash":"$(etag)","fname":"$(fname)","fsize":"$(fsize)","ext":"$(ext)","unique":"$(x:unique)","user":"$(x:user)"}`,
|
||||
CallbackBodyType: "application/json",
|
||||
Expires: ttl,
|
||||
}
|
||||
putPolicy.SetCallbackUrl(callbackURL).
|
||||
SetCallbackBody(`{"key":"$(key)","hash":"$(etag)","fname":"$(fname)","fsize":"$(fsize)","ext":"$(ext)","unique":"$(x:unique)","user":"$(x:user)"}`).
|
||||
SetCallbackBodyType("application/json")
|
||||
return uptoken.NewSigner(putPolicy, q.credentials).GetUpToken(context.Background())
|
||||
return putPolicy.UploadToken(q.mac)
|
||||
}
|
||||
|
||||
func (q *qiNiu) TimestampSecuritySign(urlStr string, ttl time.Duration) (string, error) {
|
||||
deadline := time.Now().Add(ttl).Unix()
|
||||
tUrl, err := cdn.CreateTimestampAntileechURL(urlStr, q.securityKey, deadline)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return tUrl, nil
|
||||
func (q *qiNiu) GetPrivateURL(key string, ttl uint64) string {
|
||||
deadline := time.Now().Add(time.Second * time.Duration(ttl)).Unix()
|
||||
return storage.MakePrivateURL(q.mac, q.domain, key, deadline)
|
||||
}
|
||||
|
||||
func (q *qiNiu) UploadFile(key, localFile, callbackURL string) (*PutRet, error) {
|
||||
putPolicy, err := uptoken.NewPutPolicy(q.bucket, time.Now().Add(q.uploadTokenTTL))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
putPolicy.SetCallbackUrl(callbackURL).
|
||||
SetCallbackBody(`{"key":"$(key)","hash":"$(etag)","fname":"$(fname)","fsize":"$(fsize)","ext":"$(ext)","unique":"$(x:unique)","user":"$(x:user)"}`).
|
||||
SetCallbackBodyType("application/json")
|
||||
func (q *qiNiu) VerifyCallback(req *http.Request) (bool, error) {
|
||||
return q.mac.VerifyCallback(req)
|
||||
}
|
||||
|
||||
ret := &PutRet{}
|
||||
func (q *qiNiu) UploadFile(key, localFile string) (*PutRet, error) {
|
||||
upToken := q.GetUploadToken(q.uploadTokenTTL)
|
||||
|
||||
//构建表单上传的对象
|
||||
formUploader := storage.NewFormUploader(q.conf)
|
||||
|
||||
//请求参数
|
||||
filename := path.Base(key)
|
||||
fileSuffix := path.Ext(key)
|
||||
filePrefix := filename[0 : len(filename)-len(fileSuffix)]
|
||||
uploadManager := uploader.NewUploadManager(&uploader.UploadManagerOptions{})
|
||||
err = uploadManager.UploadFile(context.Background(), localFile, &uploader.ObjectOptions{
|
||||
UpToken: uptoken.NewSigner(putPolicy, q.credentials),
|
||||
ObjectName: &key,
|
||||
CustomVars: map[string]string{
|
||||
"unique": filePrefix,
|
||||
"user": "api",
|
||||
putExtra := &storage.PutExtra{
|
||||
Params: map[string]string{
|
||||
"x:unique": filePrefix,
|
||||
"x:user": "-",
|
||||
},
|
||||
}, ret)
|
||||
}
|
||||
|
||||
//自定义返回body
|
||||
ret := new(PutRet)
|
||||
|
||||
err := formUploader.PutFile(context.Background(), ret, upToken, key, localFile, putExtra)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -142,73 +136,84 @@ func (q *qiNiu) UploadFile(key, localFile, callbackURL string) (*PutRet, error)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (q *qiNiu) GetPrivateURL(key string, ttl time.Duration) (string, error) {
|
||||
urlsProvider := downloader.SignURLsProvider(
|
||||
downloader.NewStaticDomainBasedURLsProvider([]string{q.domain}),
|
||||
downloader.NewCredentialsSigner(q.credentials),
|
||||
&downloader.SignOptions{
|
||||
TTL: ttl,
|
||||
})
|
||||
iter, err := urlsProvider.GetURLsIter(context.Background(), key, &downloader.GenerateOptions{BucketName: q.bucket})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res := url.URL{}
|
||||
peek, err := iter.Peek(&res)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if peek {
|
||||
return res.String(), nil
|
||||
}
|
||||
return "", errors.New("get private url false")
|
||||
}
|
||||
func (q *qiNiu) ResumeUploadFile(key, localFile string) (*PutRet, error) {
|
||||
upToken := q.GetUploadToken(q.uploadTokenTTL)
|
||||
|
||||
func (q *qiNiu) VerifyCallback(req *http.Request) (bool, error) {
|
||||
return q.credentials.VerifyCallback(req)
|
||||
}
|
||||
//构建分片上传的对象
|
||||
resumeUploader := storage.NewResumeUploaderV2(q.conf)
|
||||
|
||||
func (q *qiNiu) GetFileInfo(key string) (*objects.ObjectDetails, error) {
|
||||
objectInfo, err := q.bucketManager.Object(key).Stat().Call(context.Background())
|
||||
//请求参数
|
||||
filename := path.Base(key)
|
||||
fileSuffix := path.Ext(key)
|
||||
filePrefix := filename[0 : len(filename)-len(fileSuffix)]
|
||||
putExtra := &storage.RputV2Extra{
|
||||
CustomVars: map[string]string{
|
||||
"x:unique": filePrefix,
|
||||
"x:user": "-",
|
||||
},
|
||||
}
|
||||
|
||||
//自定义返回body
|
||||
ret := new(PutRet)
|
||||
|
||||
err := resumeUploader.PutFile(context.Background(), ret, upToken, key, localFile, putExtra)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return objectInfo, nil
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (q *qiNiu) DelFile(key string) error {
|
||||
err := q.bucketManager.Object(key).Delete().Call(context.Background())
|
||||
err := q.bucketManager.Delete(q.bucket, key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *qiNiu) ListFiles(keyPrefix, marker string, limit uint64) ([]objects.ObjectDetails, error) {
|
||||
iter := q.bucketManager.List(context.Background(), &objects.ListObjectsOptions{
|
||||
Limit: &limit,
|
||||
Prefix: keyPrefix,
|
||||
Marker: marker,
|
||||
})
|
||||
defer func() {
|
||||
_ = iter.Close()
|
||||
}()
|
||||
objectInfos := make([]objects.ObjectDetails, 0)
|
||||
var objectInfo objects.ObjectDetails
|
||||
for iter.Next(&objectInfo) {
|
||||
objectInfos = append(objectInfos, objectInfo)
|
||||
func (q *qiNiu) TimestampSecuritySign(path string, ttl time.Duration) string {
|
||||
sep := "/"
|
||||
path = strings.Trim(path, sep)
|
||||
splits := strings.Split(path, sep)
|
||||
for i, split := range splits {
|
||||
splits[i] = url.QueryEscape(split)
|
||||
}
|
||||
if err := iter.Error(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return objectInfos, nil
|
||||
path = sep + strings.Join(splits, sep)
|
||||
|
||||
unix := time.Now().Add(ttl).Unix()
|
||||
hex := fmt.Sprintf("%x", unix)
|
||||
|
||||
encrypt := q.md5.Encrypt(q.securityKey + path + hex)
|
||||
|
||||
param := make(url.Values)
|
||||
param.Set("sign", encrypt)
|
||||
param.Set("t", hex)
|
||||
|
||||
return param.Encode()
|
||||
}
|
||||
|
||||
func (q *qiNiu) GetFileHash(path string, qhash Qhash) (hash string, err error) {
|
||||
sign, err := q.TimestampSecuritySign(path, time.Second*5)
|
||||
if err != nil {
|
||||
return "", err
|
||||
func (q *qiNiu) GetFileInfo(key string) *storage.FileInfo {
|
||||
fileInfo, sErr := q.bucketManager.Stat(q.bucket, key)
|
||||
if sErr != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &fileInfo
|
||||
}
|
||||
|
||||
func (q *qiNiu) ListFiles(prefix, delimiter, marker string, limit int) (entries []storage.ListItem,
|
||||
commonPrefixes []string, nextMarker string, hasNext bool, err error) {
|
||||
return q.bucketManager.ListFiles(q.bucket, prefix, delimiter, marker, limit)
|
||||
}
|
||||
|
||||
func (q *qiNiu) GetFileHash(path, qhash string) (hash string, err error) {
|
||||
if !tool.InArray(qhash, []string{"sha1", "md5", "sha256"}) {
|
||||
return "", errors.New("qhash invalid")
|
||||
}
|
||||
|
||||
sign := q.TimestampSecuritySign(path, time.Second*5)
|
||||
addr := fmt.Sprintf("%s/%s?%s&qhash/%s", strings.TrimRight(q.domain, "/"), path, sign, qhash)
|
||||
|
||||
resp, err := http.Get(addr)
|
||||
|
Loading…
Reference in New Issue
Block a user