diff --git a/cmd/asyncfetch.go b/cmd/asyncfetch.go index b83560ed..a73f6294 100644 --- a/cmd/asyncfetch.go +++ b/cmd/asyncfetch.go @@ -6,7 +6,7 @@ import ( "strconv" "time" - "github.com/qiniu/api.v7/v7/storage" + "github.com/qiniu/go-sdk/v7/storage" "github.com/qiniu/qshell/v2/iqshell" "github.com/spf13/cobra" ) diff --git a/cmd/cdn.go b/cmd/cdn.go index 4fdfb4d1..ab7ec2c9 100644 --- a/cmd/cdn.go +++ b/cmd/cdn.go @@ -9,7 +9,7 @@ import ( "time" "github.com/astaxie/beego/logs" - "github.com/qiniu/api.v7/v7/cdn" + "github.com/qiniu/go-sdk/v7/cdn" "github.com/qiniu/qshell/v2/iqshell" "github.com/spf13/cobra" ) diff --git a/cmd/putfile.go b/cmd/putfile.go index 2778a4d6..4fa2d611 100644 --- a/cmd/putfile.go +++ b/cmd/putfile.go @@ -7,7 +7,7 @@ import ( "strings" "time" - "github.com/qiniu/api.v7/v7/storage" + "github.com/qiniu/go-sdk/v7/storage" "github.com/qiniu/qshell/v2/iqshell" "github.com/spf13/cobra" ) @@ -19,6 +19,7 @@ var upSettings = storage.Settings{ } var ( + isResumeV2 bool pOverwrite bool mimeType string fileType int @@ -52,6 +53,7 @@ func init() { formPutCmd.Flags().StringVarP(&callbackUrls, "callback-urls", "l", "", "upload callback urls, separated by comma") formPutCmd.Flags().StringVarP(&callbackHost, "callback-host", "T", "", "upload callback host") + RePutCmd.Flags().BoolVarP(&isResumeV2, "v2", "", false, "use resumable upload v2 APIs to upload") RePutCmd.Flags().BoolVarP(&pOverwrite, "overwrite", "w", false, "overwrite mode") RePutCmd.Flags().StringVarP(&mimeType, "mimetype", "t", "", "file mime type") RePutCmd.Flags().IntVarP(&fileType, "storage", "s", 0, "storage type") @@ -224,7 +226,6 @@ func ResumablePut(cmd *cobra.Command, params []string) { policy.CallbackBodyType = "application/x-www-form-urlencoded" } - var putExtra storage.RputExtra var upHost string if rupHost == "" { @@ -232,12 +233,6 @@ func ResumablePut(cmd *cobra.Command, params []string) { } else { upHost = rupHost } - putExtra = storage.RputExtra{ - UpHost: upHost, - } - if mimeType != "" { - putExtra.MimeType = mimeType - } mac, err := iqshell.GetMac() if err != nil { @@ -252,8 +247,31 @@ func ResumablePut(cmd *cobra.Command, params []string) { fmt.Printf("Uploading %s => %s : %s ...\n", localFile, bucket, key) - resume_uploader := storage.NewResumeUploader(nil) - err = resume_uploader.PutFile(context.Background(), &putRet, uptoken, key, localFile, &putExtra) + if isResumeV2 { + + resume_uploader := storage.NewResumeUploaderV2(nil) + + putExtra := storage.RputV2Extra{ + UpHost: upHost, + } + if mimeType != "" { + putExtra.MimeType = mimeType + } + + err = resume_uploader.PutFile(context.Background(), &putRet, uptoken, key, localFile, &putExtra) + } else { + + resume_uploader := storage.NewResumeUploader(nil) + + putExtra := storage.RputExtra{ + UpHost: upHost, + } + if mimeType != "" { + putExtra.MimeType = mimeType + } + + err = resume_uploader.PutFile(context.Background(), &putRet, uptoken, key, localFile, &putExtra) + } fmt.Println() if err != nil { diff --git a/cmd/qupload.go b/cmd/qupload.go index 2f698d4d..0002c3a7 100644 --- a/cmd/qupload.go +++ b/cmd/qupload.go @@ -9,7 +9,7 @@ import ( "strings" "github.com/astaxie/beego/logs" - "github.com/qiniu/api.v7/v7/storage" + "github.com/qiniu/go-sdk/v7/storage" "github.com/qiniu/qshell/v2/iqshell" "github.com/spf13/cobra" ) diff --git a/cmd/qupload2.go b/cmd/qupload2.go index 56156338..7f88e8aa 100644 --- a/cmd/qupload2.go +++ b/cmd/qupload2.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/astaxie/beego/logs" - "github.com/qiniu/api.v7/v7/storage" + "github.com/qiniu/go-sdk/v7/storage" "github.com/qiniu/qshell/v2/iqshell" "github.com/spf13/cobra" ) @@ -25,6 +25,7 @@ var ( func init() { qUpload2Cmd.Flags().Int64Var(&up2threadCount, "thread-count", 0, "multiple thread count") + qUpload2Cmd.Flags().BoolVarP(&uploadConfig.ResumableAPIV2, "resumable-api-v2", "", false, "use resumable upload v2 APIs to upload") qUpload2Cmd.Flags().StringVar(&uploadConfig.SrcDir, "src-dir", "", "src dir to upload") qUpload2Cmd.Flags().StringVar(&uploadConfig.FileList, "file-list", "", "file list to upload") qUpload2Cmd.Flags().StringVar(&uploadConfig.Bucket, "bucket", "", "bucket") diff --git a/cmd/root.go b/cmd/root.go index 45effb61..6bf8d47e 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -9,8 +9,8 @@ import ( "github.com/astaxie/beego/logs" homedir "github.com/mitchellh/go-homedir" - "github.com/qiniu/api.v7/v7/client" - "github.com/qiniu/api.v7/v7/storage" + "github.com/qiniu/go-sdk/v7/client" + "github.com/qiniu/go-sdk/v7/storage" "github.com/qiniu/qshell/v2/iqshell" "github.com/spf13/cobra" "github.com/spf13/viper" diff --git a/cmd/rs.go b/cmd/rs.go index 3bb23fd1..da1b09b0 100644 --- a/cmd/rs.go +++ b/cmd/rs.go @@ -7,7 +7,7 @@ import ( "strings" "time" - "github.com/qiniu/api.v7/v7/storage" + "github.com/qiniu/go-sdk/v7/storage" "github.com/qiniu/qshell/v2/iqshell" "github.com/spf13/cobra" ) diff --git a/cmd/rsbatch.go b/cmd/rsbatch.go index b7a05f5a..82397715 100644 --- a/cmd/rsbatch.go +++ b/cmd/rsbatch.go @@ -11,7 +11,7 @@ import ( "sync" "time" - "github.com/qiniu/api.v7/v7/storage" + "github.com/qiniu/go-sdk/v7/storage" "github.com/qiniu/qshell/v2/iqshell" "github.com/spf13/cobra" ) diff --git a/cmd/sync.go b/cmd/sync.go index f671e44f..e14e1d77 100644 --- a/cmd/sync.go +++ b/cmd/sync.go @@ -23,6 +23,7 @@ var ( ) func init() { + syncCmd.Flags().BoolVarP(&isResumeV2, "resumable-api-v2", "", false, "use resumable upload v2 APIs to upload") syncCmd.Flags().StringVarP(&upHostIp, "uphost", "u", "", "upload host") syncCmd.Flags().StringVarP(&saveKey, "key", "k", "", "save as in bucket") RootCmd.AddCommand(syncCmd) @@ -50,7 +51,7 @@ func Sync(cmd *cobra.Command, params []string) { bm := iqshell.GetBucketManager() //sync tStart := time.Now() - syncRet, sErr := bm.Sync(srcResUrl, bucket, key, upHostIp) + syncRet, sErr := bm.Sync(srcResUrl, bucket, key, upHostIp, isResumeV2) if sErr != nil { logs.Error(sErr) os.Exit(iqshell.STATUS_ERROR) diff --git a/cmd/token.go b/cmd/token.go index 5d811073..84d88967 100644 --- a/cmd/token.go +++ b/cmd/token.go @@ -10,9 +10,9 @@ import ( "os" "strings" - "github.com/qiniu/api.v7/v7/auth/qbox" - "github.com/qiniu/api.v7/v7/conf" - "github.com/qiniu/api.v7/v7/storage" + "github.com/qiniu/go-sdk/v7/auth/qbox" + "github.com/qiniu/go-sdk/v7/conf" + "github.com/qiniu/go-sdk/v7/storage" "github.com/qiniu/qshell/v2/iqshell" "github.com/spf13/cobra" ) diff --git a/docs/qupload.md b/docs/qupload.md index 20bca56b..fbffa001 100644 --- a/docs/qupload.md +++ b/docs/qupload.md @@ -67,7 +67,8 @@ ThreadCount ==> 并发上传的协程数量,默认为1,即文件一个个上 "log_level" : "info", "log_rotate" : 1, "log_stdout" : false, - "file_type" : 0 + "file_type" : 0, + "resumable-api-v2" : false } ``` @@ -95,6 +96,7 @@ ThreadCount ==> 并发上传的协程数量,默认为1,即文件一个个上 |log_stdout|上传日志是否同时输出一份到标准终端,默认为false,主要在调试上传功能时可以指定为true|Y| |file_type|文件存储类型,默认为`0`(标准存储) `1`为低频存储|Y| |delete_on_success|上传成功的文件,同时删除本地文件,以达到节约磁盘的目的,比如日志归档的场景,默认为`false`,如果需要开启功能,设置为`true`即可。|Y| +|resumable-api-v2|使用分片 V2 进行上传,默认为`false`使用分片 V1 |Y| 对于那么多的参数,我们可以分为几类来解释: diff --git a/docs/qupload2.md b/docs/qupload2.md index c465c11e..a7661bec 100644 --- a/docs/qupload2.md +++ b/docs/qupload2.md @@ -49,4 +49,5 @@ Flags: --success-list string upload success file list --thread-count int multiple thread count --up-host string upload host + --resumable-api-v2 use resumable upload v2 APIs to upload ``` diff --git a/docs/rput.md b/docs/rput.md index c9011f65..bef58b6d 100644 --- a/docs/rput.md +++ b/docs/rput.md @@ -3,17 +3,13 @@ `rput`命令使用七牛支持的分片上传的方式来上传一个文件,一般文件大小较大的情况下,可以使用分片上传来有效地保证文件上传的成功。 参考文档: - -[创建块 (mkblk)](http://developer.qiniu.com/code/v6/api/kodo-api/up/mkblk.html) - -[上传片 (bput)](http://developer.qiniu.com/code/v6/api/kodo-api/up/bput.html) - -[创建文件 (mkfile)](http://developer.qiniu.com/code/v6/api/kodo-api/up/mkfile.html) +[分片上传 V1](https://developer.qiniu.com/kodo/7443/shard-to-upload) +[分片上传 V2](https://developer.qiniu.com/kodo/6364/multipartupload-interface) # 格式 ``` -qshell rput [--overwrite] [--mimetype ] [--callback-urls ] [--callback-host ] [--storage ] +qshell rput [--overwrite] [--v2] [--mimetype ] [--callback-urls ] [--callback-host ] [--storage ] ``` 其中 `Overwrite`,`MimeType`,`StorageType` (0 -> 标准存储, 1 - 低频存储)参数可根据需要指定一个或者多个,参数顺序随意,程序会自动识别。 @@ -34,16 +30,25 @@ qshell rput [--overwrite] [--mimetype ] [--callback-urls [] |Bucket|空间名称,可以为公开空间或者私有空间|N| |Key|该资源保存在空间中的名字|N| |UpHostIp|上传入口的IP地址,一般在大文件的情况下,可以指定上传入口的IP来减少DNS环节,提升同步速度|Y| +|resumable-api-v2|使用分片 v2 进行上传,默认使用 v1|Y| **备注:** @@ -46,9 +47,9 @@ $ dig up-na0.qiniu.com # 示例 -抓取一个资源并以指定的文件名保存在七牛的空间里面: +使用分片 v2 抓取一个资源并以指定的文件名保存在七牛的空间里面: ``` -$ qshell sync http://if-pbl.qiniudn.com/test_big_movie.mp4 if-pbl test.mp4 +$ qshell sync http://if-pbl.qiniudn.com/test_big_movie.mp4 if-pbl test.mp4 --resumable-api-v2 ``` diff --git a/go.mod b/go.mod index 67a742bd..4ec978db 100644 --- a/go.mod +++ b/go.mod @@ -1,29 +1,36 @@ module github.com/qiniu/qshell/v2 require ( - github.com/aliyun/aliyun-oss-go-sdk v2.1.2+incompatible - github.com/astaxie/beego v1.12.2 - github.com/aws/aws-sdk-go v1.33.0 + github.com/aliyun/aliyun-oss-go-sdk v2.1.6+incompatible + github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 // indirect + github.com/astaxie/beego v1.12.3 + github.com/aws/aws-sdk-go v1.37.31 github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect github.com/fsnotify/fsnotify v1.4.9 // indirect - github.com/golang/snappy v0.0.1 // indirect + github.com/golang/snappy v0.0.3 // indirect + github.com/magiconair/properties v1.8.4 // indirect github.com/mitchellh/go-homedir v1.1.0 - github.com/mitchellh/mapstructure v1.3.2 // indirect - github.com/pelletier/go-toml v1.8.0 // indirect - github.com/qiniu/api.v7/v7 v7.5.0 + github.com/mitchellh/mapstructure v1.4.1 // indirect + github.com/pelletier/go-toml v1.8.1 // indirect + github.com/qiniu/go-sdk/v7 v7.9.2 github.com/satori/go.uuid v1.2.0 // indirect - github.com/spf13/afero v1.3.1 // indirect + github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect + github.com/spf13/afero v1.5.1 // indirect github.com/spf13/cast v1.3.1 // indirect - github.com/spf13/cobra v1.0.0 + github.com/spf13/cobra v1.1.3 github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 - github.com/spf13/viper v1.7.0 + github.com/spf13/viper v1.7.1 github.com/stretchr/testify v1.6.1 github.com/syndtr/goleveldb v1.0.0 - golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect - golang.org/x/text v0.3.3 - golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect - gopkg.in/ini.v1 v1.57.0 // indirect + github.com/ugorji/go v1.1.4 // indirect + github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77 // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect + golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005 // indirect + golang.org/x/text v0.3.5 + golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect + golang.org/x/tools v0.0.0-20200117065230-39095c1d176c // indirect + gopkg.in/ini.v1 v1.62.0 // indirect ) go 1.13 diff --git a/go.sum b/go.sum index c7912b86..ee5fc7b3 100644 --- a/go.sum +++ b/go.sum @@ -24,14 +24,20 @@ github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGn github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk= github.com/aliyun/aliyun-oss-go-sdk v2.1.2+incompatible h1:kB3yKV/bBZLX5Rm8aOaFsM6M7ZmyOiUgAElhfn/R27c= github.com/aliyun/aliyun-oss-go-sdk v2.1.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= +github.com/aliyun/aliyun-oss-go-sdk v2.1.6+incompatible h1:Ft+KeWIJxFP76LqgJbvtOA1qBIoC8vGkTV3QeCOeJC4= +github.com/aliyun/aliyun-oss-go-sdk v2.1.6+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/astaxie/beego v1.12.2 h1:CajUexhSX5ONWDiSCpeQBNVfTzOtPb9e9d+3vuU5FuU= github.com/astaxie/beego v1.12.2/go.mod h1:TMcqhsbhN3UFpN+RCfysaxPAbrhox6QSS3NIAEp/uzE= +github.com/astaxie/beego v1.12.3 h1:SAQkdD2ePye+v8Gn1r4X6IKZM1wd28EyUOVQ3PDSOOQ= +github.com/astaxie/beego v1.12.3/go.mod h1:p3qIm0Ryx7zeBHLljmd7omloyca1s4yu1a8kM1FkpIA= github.com/aws/aws-sdk-go v1.33.0 h1:Bq5Y6VTLbfnJp1IV8EL/qUU5qO1DYHda/zis/sqevkY= github.com/aws/aws-sdk-go v1.33.0/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/aws/aws-sdk-go v1.37.31 h1:eK7hgg1H4xivwopAbnzfQ7ZBbDb9cEkGDivd9rUMnJs= +github.com/aws/aws-sdk-go v1.37.31/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA= github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ= @@ -90,7 +96,6 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -103,6 +108,8 @@ github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8l github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -153,6 +160,9 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -165,7 +175,6 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= @@ -175,6 +184,8 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY= +github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= @@ -191,6 +202,8 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg= github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -200,11 +213,9 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= -github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= @@ -213,6 +224,8 @@ github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw= github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs= +github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -237,8 +250,10 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/qiniu/api.v7/v7 v7.5.0 h1:DY6NrIp6FZ1GP4Roc9hRnO2m+OLzASYNnvz5Mbgw1rk= -github.com/qiniu/api.v7/v7 v7.5.0/go.mod h1:VE5oC5rkE1xul0u1S2N0b2Uxq9/6hZzhyqjgK25XDcM= +github.com/qiniu/go-sdk/v7 v7.9.1 h1:rnHAVNJ++gAlGJ8ZI2+vpbqgsQcksSsdaYR5o9tbTHA= +github.com/qiniu/go-sdk/v7 v7.9.1/go.mod h1:Eeqk1/Km3f1MuLUUkg2JCSg/dVkydKbBvEdJJqFgn9g= +github.com/qiniu/go-sdk/v7 v7.9.2 h1:Oqck4GUAsxJl5EpeE2L0He8Ez/YhtNfqqbhhwLJGykA= +github.com/qiniu/go-sdk/v7 v7.9.2/go.mod h1:Eeqk1/Km3f1MuLUUkg2JCSg/dVkydKbBvEdJJqFgn9g= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -248,6 +263,8 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo= github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg= +github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 h1:DAYUYH5869yV94zvCES9F51oYtN5oGlwjxJJz7ZCnik= +github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw= github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s= @@ -263,11 +280,15 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.3.1 h1:GPTpEAuNr98px18yNQ66JllNil98wfRZ/5Ukny8FeQA= github.com/spf13/afero v1.3.1/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.5.1 h1:VHu76Lk0LSP1x254maIu2bplkWpfBWI+B+6fdoZprcg= +github.com/spf13/afero v1.5.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= +github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -277,6 +298,8 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= +github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -312,6 +335,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -350,6 +374,7 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -359,6 +384,10 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -380,15 +409,22 @@ golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005 h1:pDMpM2zh2MT0kHy037cKlSby2nEhD50SYqwQk76Nm40= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -442,7 +478,6 @@ google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyz google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= @@ -453,6 +488,8 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.57.0 h1:9unxIsFcTt4I55uWluz+UmL95q4kdJ0buvQ1ZIqVQww= gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -465,6 +502,8 @@ gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/iqshell/account.go b/iqshell/account.go index db467aad..33b979c3 100644 --- a/iqshell/account.go +++ b/iqshell/account.go @@ -9,7 +9,7 @@ import ( "strings" "github.com/astaxie/beego/logs" - "github.com/qiniu/api.v7/v7/auth/qbox" + "github.com/qiniu/go-sdk/v7/auth/qbox" "github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb/opt" ) diff --git a/iqshell/bucket.go b/iqshell/bucket.go index 0ea37d58..5a7e7c33 100644 --- a/iqshell/bucket.go +++ b/iqshell/bucket.go @@ -15,10 +15,10 @@ import ( "strings" "time" - "github.com/qiniu/api.v7/v7/auth" - "github.com/qiniu/api.v7/v7/auth/qbox" - "github.com/qiniu/api.v7/v7/conf" - "github.com/qiniu/api.v7/v7/storage" + "github.com/qiniu/go-sdk/v7/auth" + "github.com/qiniu/go-sdk/v7/auth/qbox" + "github.com/qiniu/go-sdk/v7/conf" + "github.com/qiniu/go-sdk/v7/storage" ) // Get 接口返回的结构 diff --git a/iqshell/cdn.go b/iqshell/cdn.go index c30526fa..837e388d 100644 --- a/iqshell/cdn.go +++ b/iqshell/cdn.go @@ -4,8 +4,8 @@ import ( "fmt" "os" - "github.com/qiniu/api.v7/v7/auth/qbox" - "github.com/qiniu/api.v7/v7/cdn" + "github.com/qiniu/go-sdk/v7/auth/qbox" + "github.com/qiniu/go-sdk/v7/cdn" ) // 获取CdnManager diff --git a/iqshell/m3u8.go b/iqshell/m3u8.go index 61d544d4..0bcafd0d 100644 --- a/iqshell/m3u8.go +++ b/iqshell/m3u8.go @@ -13,7 +13,7 @@ import ( "strings" "time" - "github.com/qiniu/api.v7/v7/storage" + "github.com/qiniu/go-sdk/v7/storage" ) func (m *BucketManager) M3u8FileList(bucket string, m3u8Key string) (slicesToDelete []EntryPath, err error) { diff --git a/iqshell/qupload.go b/iqshell/qupload.go index 24a90070..7a3ac0d2 100644 --- a/iqshell/qupload.go +++ b/iqshell/qupload.go @@ -15,8 +15,8 @@ import ( "time" "github.com/astaxie/beego/logs" - "github.com/qiniu/api.v7/v7/auth/qbox" - "github.com/qiniu/api.v7/v7/storage" + "github.com/qiniu/go-sdk/v7/auth/qbox" + "github.com/qiniu/go-sdk/v7/storage" "github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb/opt" ) @@ -71,6 +71,7 @@ type UploadConfig struct { Bucket string `json:"bucket"` //optional config + ResumableAPIV2 bool `json:"resumable_api_v2,omitempty"` FileList string `json:"file_list,omitempty"` PutThreshold int64 `json:"put_threshold,omitempty"` KeyPrefix string `json:"key_prefix,omitempty"` @@ -831,11 +832,6 @@ var progressRecorder = NewProgressRecorder("") func resumableUploadFile(uploadConfig *UploadConfig, ldb *leveldb.DB, ldbWOpt *opt.WriteOptions, ldbKey string, upToken string, storePath, localFilePath, uploadFileKey string, localFileLastModified int64, exporter *FileExporter) { - uploader := storage.NewResumeUploader(nil) - //params - putRet := storage.PutRet{} - putExtra := storage.RputExtra{} - var progressFilePath string if !uploadConfig.DisableResume { //progress file @@ -845,16 +841,48 @@ func resumableUploadFile(uploadConfig *UploadConfig, ldb *leveldb.DB, ldbWOpt *o progressRecorder.FilePath = progressFilePath } - var notifyFunc = func(blkIdx, blkSize int, ret *storage.BlkputRet) { - logs.Debug("uploadFileKey: %s, blkIdx: %d, blkSize: %d, %v", uploadFileKey, blkIdx, blkSize, *ret) - progressRecorder.BlkCtxs = append(progressRecorder.BlkCtxs, *ret) - progressRecorder.Offset += int64(blkSize) + var err error + if uploadConfig.ResumableAPIV2 { + partSize := int64(BLOCK_SIZE) + var notifyFunc = func(partNumber int64, ret *storage.UploadPartsRet) { + logs.Debug("uploadFileKey: %s, partIdx: %d, partSize: %d, %v", uploadFileKey, partNumber, partSize, *ret) + progressRecorder.Parts = append(progressRecorder.Parts, storage.UploadPartInfo{ + Etag: ret.Etag, + PartNumber: partNumber, + }) + progressRecorder.Offset += partSize + } + + //params + putRet := storage.UploadPartsRet{} + putExtra := storage.RputV2Extra{ + PartSize: partSize, + } + putExtra.Notify = notifyFunc + putExtra.UpHost = uploadConfig.GetUpHost() + + //resumable upload + uploader := storage.NewResumeUploaderV2(nil) + err = uploader.PutFile(context.Background(), &putRet, upToken, uploadFileKey, localFilePath, &putExtra) + } else { + + var notifyFunc = func(blkIdx, blkSize int, ret *storage.BlkputRet) { + logs.Debug("uploadFileKey: %s, blkIdx: %d, blkSize: %d, %v", uploadFileKey, blkIdx, blkSize, *ret) + progressRecorder.BlkCtxs = append(progressRecorder.BlkCtxs, *ret) + progressRecorder.Offset += int64(blkSize) + } + + //params + putRet := storage.PutRet{} + putExtra := storage.RputExtra{} + putExtra.Notify = notifyFunc + putExtra.UpHost = uploadConfig.GetUpHost() + + //resumable upload + uploader := storage.NewResumeUploader(nil) + err = uploader.PutFile(context.Background(), &putRet, upToken, uploadFileKey, localFilePath, &putExtra) } - putExtra.Notify = notifyFunc - putExtra.UpHost = uploadConfig.GetUpHost() - //resumable upload - err := uploader.PutFile(context.Background(), &putRet, upToken, uploadFileKey, localFilePath, &putExtra) if err != nil { atomic.AddInt64(&failureFileCount, 1) logs.Error("Resumable upload file `%s` => `%s` failed due to nerror `%v`", localFilePath, uploadFileKey, err) diff --git a/iqshell/rs_fop.go b/iqshell/rs_fop.go index c6634902..73ab556a 100644 --- a/iqshell/rs_fop.go +++ b/iqshell/rs_fop.go @@ -1,7 +1,7 @@ package iqshell import ( - "github.com/qiniu/api.v7/v7/storage" + "github.com/qiniu/go-sdk/v7/storage" ) func Prefop(persistentId string) (ret storage.PrefopRet, err error) { diff --git a/iqshell/sync.go b/iqshell/sync.go index 7e3a97d7..f646a3bb 100644 --- a/iqshell/sync.go +++ b/iqshell/sync.go @@ -15,7 +15,7 @@ import ( "time" "github.com/astaxie/beego/logs" - "github.com/qiniu/api.v7/v7/storage" + "github.com/qiniu/go-sdk/v7/storage" ) //range get and chunk upload @@ -27,17 +27,21 @@ const ( ) type ProgressRecorder struct { - BlkCtxs []storage.BlkputRet `json:"blk_ctxs"` - Offset int64 `json:"offset"` - TotalSize int64 `json:"total_size"` - LastModified int `json:"last_modified"` // 上传文件的modification time - FilePath string // 断点续传记录保存文件 + BlkCtxs []storage.BlkputRet `json:"blk_ctxs"` // resume v1 + Parts []storage.UploadPartInfo `json:"parts"` // resume v2 + UploadId string `json:"upload_id"` // resume v2 + ExpireTime int64 `json:"expire_time"` // resume v2 + Offset int64 `json:"offset"` + TotalSize int64 `json:"total_size"` + LastModified int `json:"last_modified"` // 上传文件的modification time + FilePath string // 断点续传记录保存文件 } func NewProgressRecorder(filePath string) *ProgressRecorder { p := new(ProgressRecorder) p.FilePath = filePath p.BlkCtxs = make([]storage.BlkputRet, 0) + p.Parts = make([]storage.UploadPartInfo, 0) return p } @@ -96,9 +100,10 @@ func (p *ProgressRecorder) Reset() { p.Offset = 0 p.TotalSize = 0 p.BlkCtxs = make([]storage.BlkputRet, 0) + p.Parts = make([]storage.UploadPartInfo, 0) } -func (p *ProgressRecorder) CheckValid(fileSize int64, lastModified int) { +func (p *ProgressRecorder) CheckValid(fileSize int64, lastModified int, isResumableV2 bool) { //check offset valid or not if p.Offset%BLOCK_SIZE != 0 { @@ -107,30 +112,67 @@ func (p *ProgressRecorder) CheckValid(fileSize int64, lastModified int) { return } - //check offset and blk ctxs - if p.Offset != 0 && p.BlkCtxs != nil { - if int(p.Offset/BLOCK_SIZE) != len(p.BlkCtxs) { - logs.Info("Invalid offset and block contexts") + // 分片 V1 + if !isResumableV2 { + //check offset and blk ctxs + if p.Offset != 0 && p.BlkCtxs != nil && int(p.Offset/BLOCK_SIZE) != len(p.BlkCtxs) { + + logs.Info("Invalid offset and block info") + p.Reset() + return + } + + //check blk ctxs, when no progress found + if p.Offset == 0 || p.BlkCtxs == nil { p.Reset() return } + + if fileSize != p.TotalSize { + if p.TotalSize != 0 { + logs.Warning("Remote file length changed, progress file out of date") + } + p.Offset = 0 + p.TotalSize = fileSize + p.BlkCtxs = make([]storage.BlkputRet, 0) + return + } + + if len(p.BlkCtxs) > 0 { + if lastModified != 0 && p.LastModified != lastModified { + p.Reset() + } + } + + return + } + + // 分片 V2 + //check offset and blk ctxs + if p.Offset != 0 && p.Parts != nil && int(p.Offset/BLOCK_SIZE) != len(p.Parts) { + + logs.Info("Invalid offset and block info") + p.Reset() + return } //check blk ctxs, when no progress found - if p.Offset == 0 || p.BlkCtxs == nil { + if p.Offset == 0 || p.Parts == nil { p.Reset() return } + if fileSize != p.TotalSize { if p.TotalSize != 0 { logs.Warning("Remote file length changed, progress file out of date") } p.Offset = 0 p.TotalSize = fileSize - p.BlkCtxs = make([]storage.BlkputRet, 0) + p.Parts = make([]storage.UploadPartInfo, 0) return } - if len(p.BlkCtxs) > 0 { + + if len(p.Parts) > 0 { if lastModified != 0 && p.LastModified != lastModified { p.Reset() } @@ -188,7 +230,7 @@ type SputRet struct { Fsize int64 `json:"fsize"` } -func (m *BucketManager) Sync(srcResUrl, bucket, key, upHost string) (putRet SputRet, err error) { +func (m *BucketManager) Sync(srcResUrl, bucket, key, upHost string, isResumableV2 bool) (putRet SputRet, err error) { exists, cErr := m.CheckExists(bucket, key) if cErr != nil { @@ -212,7 +254,8 @@ func (m *BucketManager) Sync(srcResUrl, bucket, key, upHost string) (putRet Sput } syncProgress := NewProgressRecorder(progressFile) syncProgress.RecoverFromUrl(srcResUrl, bucket, key) - syncProgress.CheckValid(totalSize, 0) + syncProgress.CheckValid(totalSize, 0, isResumableV2) + syncProgress.TotalSize = totalSize //get total block count fmt.Println("totalSize: ", totalSize) @@ -248,9 +291,48 @@ func (m *BucketManager) Sync(srcResUrl, bucket, key, upHost string) (putRet Sput return } } + + var uploader IResumeUploader + if isResumableV2 { + uploader = &resumeUploaderV2{ + uploader: storage.NewResumeUploaderV2(nil), + recorder: syncProgress, + upHost: upHost, + bucket: bucket, + uptoken: uptoken, + key: key, + } + } else { + uploader = &resumeUploaderV1{ + uploader: storage.NewResumeUploader(nil), + recorder: syncProgress, + key: key, + upHost: upHost, + uptoken: uptoken, + } + } + + // 1. 初始化服务 + retryTimes := 0 + for { + pErr := uploader.initServer(ctx) + if pErr != nil && retryTimes >= RETRY_MAX_TIMES { + err = pErr + return + } + if pErr == nil { + break + } + logs.Error(pErr.Error()) + time.Sleep(RETRY_INTERVAL) + + logs.Info("Retrying %d time for init server", retryTimes) + retryTimes++ + } + //range get and mkblk upload var bf *bytes.Buffer - var blockSize = BLOCK_SIZE + var blockSize = int64(BLOCK_SIZE) for blkIndex := fromBlkIndex; blkIndex < totalBlkCnt; blkIndex++ { if blkIndex == totalBlkCnt-1 { lastBlock = true @@ -259,11 +341,11 @@ func (m *BucketManager) Sync(srcResUrl, bucket, key, upHost string) (putRet Sput syncPercent := fmt.Sprintf("%.2f", float64(blkIndex+1)*100.0/float64(totalBlkCnt)) logs.Info(fmt.Sprintf("Syncing block %d [%s%%] ...", blkIndex, syncPercent)) - var blkCtx storage.BlkputRet + // 2.1 获取上传数据 var retryTimes int var rErr error for { - bf, rErr = getRange(srcResUrl, totalSize, rangeStartOffset, BLOCK_SIZE, lastBlock) + bf, rErr = getRange(srcResUrl, totalSize, rangeStartOffset, blockSize, lastBlock) if rErr != nil && retryTimes >= RETRY_MAX_TIMES { err = errors.New(strings.Join([]string{"Get range block data failed: ", rErr.Error()}, "")) return @@ -277,12 +359,11 @@ func (m *BucketManager) Sync(srcResUrl, bucket, key, upHost string) (putRet Sput retryTimes++ } data := bf.Bytes() - if lastBlock { - blockSize = len(data) - } + + // 2.2 上传数据到云存储 retryTimes = 0 for { - pErr := resumeUploader.Mkblk(ctx, uptoken, upHost, &blkCtx, blockSize, bytes.NewReader(data), len(data)) + pErr := uploader.uploadBlock(ctx, data) if pErr != nil && retryTimes >= RETRY_MAX_TIMES { err = pErr return @@ -293,15 +374,12 @@ func (m *BucketManager) Sync(srcResUrl, bucket, key, upHost string) (putRet Sput logs.Error(pErr.Error()) time.Sleep(RETRY_INTERVAL) - logs.Info("Retrying %d time mkblk for block [%d]", retryTimes, blkIndex) + logs.Info("Retrying %d time for upload block index:[%d]", retryTimes, blkIndex) retryTimes++ } //advance range offset rangeStartOffset += BLOCK_SIZE - syncProgress.BlkCtxs = append(syncProgress.BlkCtxs, blkCtx) - syncProgress.Offset = rangeStartOffset - sErr := syncProgress.RecordProgress() if sErr != nil { logs.Info(rErr.Error()) @@ -309,13 +387,22 @@ func (m *BucketManager) Sync(srcResUrl, bucket, key, upHost string) (putRet Sput } //make file - putExtra := storage.RputExtra{ - Progresses: syncProgress.BlkCtxs, - } - mkErr := resumeUploader.Mkfile(ctx, uptoken, upHost, &putRet, key, true, totalSize, &putExtra) - if mkErr != nil { - err = fmt.Errorf("Mkfile error, %s", mkErr.Error()) - return + retryTimes = 0 + for { + ret, pErr := uploader.complete(ctx) + if pErr != nil && retryTimes >= RETRY_MAX_TIMES { + err = fmt.Errorf("Mkfile error, %s", err.Error()) + return + } + if pErr == nil { + putRet = ret + break + } + logs.Error(pErr.Error()) + time.Sleep(RETRY_INTERVAL) + + logs.Info("Retrying %d time for server to create file", retryTimes) + retryTimes++ } //delete progress file @@ -362,11 +449,6 @@ func getRange(srcResUrl string, totalSize, rangeStartOffset, rangeBlockSize int6 } defer dResp.Body.Close() - //fmt.Println("-------------------") - //fmt.Println(dResp.StatusCode) - //for k, v := range dResp.Header { - // fmt.Println(k, ":", strings.Join(v, ",")) - //} //status error if dResp.StatusCode/100 != 2 { diff --git a/iqshell/uploader.go b/iqshell/uploader.go index 4f7c6c93..6fb3a188 100644 --- a/iqshell/uploader.go +++ b/iqshell/uploader.go @@ -1,7 +1,12 @@ package iqshell import ( - "github.com/qiniu/api.v7/v7/storage" + "bytes" + "context" + "crypto/md5" + "encoding/hex" + "github.com/qiniu/go-sdk/v7/storage" + "time" ) type ResumeUploader struct { @@ -19,3 +24,97 @@ func NewResumeUploader(cfg *storage.Config) *ResumeUploader { ResumeUploader: rUploader, } } + +type IResumeUploader interface { + initServer(ctx context.Context) error + uploadBlock(ctx context.Context, data []byte) error + complete(ctx context.Context) (putRet SputRet, err error) +} + +type resumeUploaderV1 struct { + uploader *storage.ResumeUploader + recorder *ProgressRecorder + uptoken string + key string + upHost string +} + +func (uploader *resumeUploaderV1) initServer(ctx context.Context) error { + return nil +} + +// size 必须是 4M 整数倍 +func (uploader *resumeUploaderV1) uploadBlock(ctx context.Context, data []byte) error { + size := len(data) + var blkCtx storage.BlkputRet + err := uploader.uploader.Mkblk(ctx, uploader.uptoken, uploader.upHost, &blkCtx, size, bytes.NewReader(data), size) + if err == nil { + uploader.recorder.BlkCtxs = append(uploader.recorder.BlkCtxs, blkCtx) + uploader.recorder.Offset += int64(size) + } + return err +} + +func (uploader *resumeUploaderV1) complete(ctx context.Context) (putRet SputRet, err error) { + putExtra := storage.RputExtra{ + Progresses: uploader.recorder.BlkCtxs, + } + err = uploader.uploader.Mkfile(ctx, uploader.uptoken, uploader.upHost, &putRet, uploader.key, true, uploader.recorder.TotalSize, &putExtra) + return +} + +type resumeUploaderV2 struct { + uploader *storage.ResumeUploaderV2 + recorder *ProgressRecorder + upHost string + bucket string + uptoken string + key string +} + +func (uploader *resumeUploaderV2) initServer(ctx context.Context) error { + // uploadId 存在且有效 + if now := time.Now().Unix(); + len(uploader.recorder.UploadId) > 0 && now < uploader.recorder.ExpireTime { + return nil + } + + hasKey := len(uploader.key) != 0 + ret := &storage.InitPartsRet{} + err := uploader.uploader.InitParts(ctx, uploader.uptoken, uploader.upHost, uploader.bucket, + uploader.key, hasKey, ret) + if err == nil { + uploader.recorder.UploadId = ret.UploadID + uploader.recorder.ExpireTime = time.Now().Unix() + 3600*24*5 + } + return err +} + +func (uploader *resumeUploaderV2) uploadBlock(ctx context.Context, data []byte) error { + hasKey := len(uploader.key) != 0 + partNumber := int64(len(uploader.recorder.Parts)) + 1 + size := len(data) + partMd5 := md5.Sum(data) + partMd5String := hex.EncodeToString(partMd5[:]) + ret := &storage.UploadPartsRet{} + err := uploader.uploader.UploadParts(ctx, uploader.uptoken, uploader.upHost, uploader.bucket, + uploader.key, hasKey, uploader.recorder.UploadId, partNumber, partMd5String, ret, bytes.NewReader(data), size) + if err == nil { + uploader.recorder.Parts = append(uploader.recorder.Parts, storage.UploadPartInfo{ + Etag: ret.Etag, + PartNumber: partNumber, + }) + uploader.recorder.Offset += int64(size) + } + return err +} + +func (uploader *resumeUploaderV2) complete(ctx context.Context) (putRet SputRet, err error) { + hasKey := len(uploader.key) != 0 + putExtra := &storage.RputV2Extra{ + Progresses: uploader.recorder.Parts, + } + err = uploader.uploader.CompleteParts(ctx, uploader.uptoken, uploader.upHost, &putRet, uploader.bucket, + uploader.key, hasKey, uploader.recorder.UploadId, putExtra) + return +} diff --git a/iqshell/utils.go b/iqshell/utils.go index d5f051ca..757d9b04 100644 --- a/iqshell/utils.go +++ b/iqshell/utils.go @@ -12,7 +12,7 @@ import ( "strings" "syscall" - "github.com/qiniu/api.v7/v7/storage" + "github.com/qiniu/go-sdk/v7/storage" ) const (