123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- package qiniu
- import (
- "context"
- "errors"
- "fmt"
- "git.bvbej.com/bvbej/base-golang/pkg/md5"
- "git.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"
- "net/url"
- "path"
- "strings"
- "time"
- )
- var _ QiNiu = (*qiNiu)(nil)
- type QiNiu interface {
- 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)
- UploadFile(key, localFile string) (*PutRet, error)
- ResumeUploadFile(key, localFile string) (*PutRet, error)
- DelFile(key string) 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
- md5 md5.MD5
- uploadTokenTTL uint64
- }
- type PutRet struct {
- Key string `json:"key"`
- Hash string `json:"hash"`
- Fsize string `json:"fsize"`
- Fname string `json:"fname"`
- Ext string `json:"ext"`
- Unique string `json:"unique"`
- User string `json:"user"`
- }
- func New(accessKey, secretKey, bucket, domain, securityKey string) QiNiu {
- region, _ := storage.GetRegion(accessKey, bucket)
- mac := qbox.NewMac(accessKey, secretKey)
- conf := &storage.Config{
- Region: region, //空间所在的存储区域
- UseHTTPS: true, //是否使用https域名
- UseCdnDomains: true, //上传是否使用CDN上传加速
- }
- return &qiNiu{
- mac: mac,
- bucketManager: storage.NewBucketManager(mac, conf),
- bucket: bucket,
- domain: domain,
- securityKey: securityKey,
- conf: conf,
- md5: md5.New(),
- uploadTokenTTL: 3600,
- }
- }
- func (q *qiNiu) i() {}
- func (q *qiNiu) SetDefaultUploadTokenTTL(ttl uint64) {
- q.uploadTokenTTL = ttl
- }
- func (q *qiNiu) GetUploadToken(ttl uint64) string {
- putPolicy := storage.PutPolicy{
- Scope: q.bucket,
- Expires: ttl,
- }
- return putPolicy.UploadToken(q.mac)
- }
- 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,
- }
- return putPolicy.UploadToken(q.mac)
- }
- 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) VerifyCallback(req *http.Request) (bool, error) {
- return q.mac.VerifyCallback(req)
- }
- 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)]
- putExtra := &storage.PutExtra{
- Params: map[string]string{
- "x:unique": filePrefix,
- "x:user": "-",
- },
- }
- //自定义返回body
- ret := new(PutRet)
- err := formUploader.PutFile(context.Background(), ret, upToken, key, localFile, putExtra)
- if err != nil {
- return nil, err
- }
- return ret, nil
- }
- func (q *qiNiu) ResumeUploadFile(key, localFile string) (*PutRet, error) {
- upToken := q.GetUploadToken(q.uploadTokenTTL)
- //构建分片上传的对象
- resumeUploader := storage.NewResumeUploaderV2(q.conf)
- //请求参数
- 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 ret, nil
- }
- func (q *qiNiu) DelFile(key string) error {
- err := q.bucketManager.Delete(q.bucket, key)
- if err != nil {
- return err
- }
- return nil
- }
- 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)
- }
- 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) 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("https://cdn.mogume.com/%s?%s&qhash/%s", path, sign, qhash)
- resp, err := http.Get(addr)
- defer func() { _ = resp.Body.Close() }()
- if err != nil {
- return "", err
- }
- if resp.StatusCode != http.StatusOK {
- return "", errors.New(resp.Status)
- }
- body, err := io.ReadAll(resp.Body)
- if err != nil {
- return "", err
- }
- return gjson.GetBytes(body, "hash").String(), nil
- }
|