diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cc33eee..13aa3461 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # 2.3.6 1. 修复m3u8replace 上传的问题 +2. 加入reportCard检测代码质量 # 2.3.5 1. 增加token命令,创建Qbox token, qiniuToken, uploadToken diff --git a/cmd/account.go b/cmd/account.go index 0d0772c6..6b42a625 100644 --- a/cmd/account.go +++ b/cmd/account.go @@ -28,6 +28,7 @@ var cmdAccount = &cobra.Command{ Run: Account, } +// 【account】获取本地保存的用户的AK/AK/Name信息; 设置保存用户AK/SK信息到本地 func Account(cmd *cobra.Command, params []string) { if len(params) == 0 { account, gErr := iqshell.GetAccount() diff --git a/cmd/alilistbucket.go b/cmd/alilistbucket.go index 00b7c637..792ad063 100644 --- a/cmd/alilistbucket.go +++ b/cmd/alilistbucket.go @@ -17,6 +17,7 @@ func init() { RootCmd.AddCommand(aliCmd) } +// 【alilistbucket】列举阿里空间中的文件列表 func AliListBucket(cmd *cobra.Command, params []string) { dataCenter := params[0] bucket := params[1] diff --git a/cmd/bucket.go b/cmd/bucket.go index 4c98a689..59179d03 100644 --- a/cmd/bucket.go +++ b/cmd/bucket.go @@ -31,6 +31,7 @@ func init() { RootCmd.AddCommand(bucketsCmd, domainsCmd) } +// 【buckets】获取一个用户的所有的存储空间 func GetBuckets(cmd *cobra.Command, params []string) { bm := iqshell.GetBucketManager() @@ -49,6 +50,7 @@ func GetBuckets(cmd *cobra.Command, params []string) { } } +// 【domains】获取一个空间绑定的CDN域名 func GetDomainsOfBucket(cmd *cobra.Command, params []string) { bucket := params[0] bm := iqshell.GetBucketManager() diff --git a/cmd/cdn.go b/cmd/cdn.go index e02a6140..22848d09 100644 --- a/cmd/cdn.go +++ b/cmd/cdn.go @@ -12,9 +12,14 @@ import ( ) const ( + // CDN刷新一次性最大的刷新文件列表 BATCH_CDN_REFRESH_URLS_ALLOW_MAX = 100 + + // CDN目录刷新一次性最大的刷新目录数 BATCH_CDN_REFRESH_DIRS_ALLOW_MAX = 10 - BATCH_CDN_PREFETCH_ALLOW_MAX = 100 + + // 预取一次最大的预取数目 + BATCH_CDN_PREFETCH_ALLOW_MAX = 100 ) var ( @@ -46,7 +51,7 @@ func init() { RootCmd.AddCommand(cdnPreCmd, cdnRefreshCmd) } -// 刷新CDN +// 【cdnrefresh】刷新所有CDN节点 func CdnRefresh(cmd *cobra.Command, params []string) { var urlListFile string @@ -123,7 +128,7 @@ func cdnRefresh(cm *cdn.CdnManager, urls []string, dirs []string) { } } -// CDN 文件预取 +// 【cdnprefetch】CDN 文件预取 func CdnPrefetch(cmd *cobra.Command, params []string) { var urlListFile string diff --git a/cmd/fop.go b/cmd/fop.go index 56274938..544541c1 100644 --- a/cmd/fop.go +++ b/cmd/fop.go @@ -30,6 +30,7 @@ func init() { RootCmd.AddCommand(prefopCmd, fopCmd) } +// 【prefop】根据persistentId查询异步处理的进度, 处理结果 func Prefop(cmd *cobra.Command, params []string) { persistentId := params[0] @@ -42,6 +43,7 @@ func Prefop(cmd *cobra.Command, params []string) { } } +// 【pfop】 提交异步处理请求 func Fop(cmd *cobra.Command, params []string) { bucket, key, fops := params[0], params[1], params[2] diff --git a/cmd/ip.go b/cmd/ip.go index f7bc3fa2..23f9231c 100644 --- a/cmd/ip.go +++ b/cmd/ip.go @@ -10,9 +10,11 @@ import ( ) const ( + // IP信息查询接口地址 TAOBAO_IP_QUERY = "http://ip.taobao.com/service/getIpInfo.php" ) +// 接口返回的IP信息 type IpInfo struct { Code int `json:"code"` Data IpData `json:"data"` @@ -22,6 +24,7 @@ func (this IpInfo) String() string { return fmt.Sprintf("%s", this.Data) } +// ip 具体的信息 type IpData struct { Country string `json:"country"` CountryId string `json:"country_id"` @@ -54,6 +57,7 @@ func init() { RootCmd.AddCommand(ipQueryCmd) } +// 【ip】查询ip的相关信息 func IpQuery(cmd *cobra.Command, params []string) { for _, ip := range params { url := fmt.Sprintf("%s?ip=%s", TAOBAO_IP_QUERY, ip) diff --git a/cmd/putfile.go b/cmd/putfile.go index 9645f7a3..7e735aa2 100644 --- a/cmd/putfile.go +++ b/cmd/putfile.go @@ -62,6 +62,7 @@ func init() { RootCmd.AddCommand(formPutCmd, RePutCmd) } +// 上传接口返回的文件信息 type PutRet struct { Key string `json:"key"` Hash string `json:"hash"` @@ -69,6 +70,7 @@ type PutRet struct { Fsize int64 `json:"fsize"` } +// 【fput】使用表单上传本地文件到七牛存储空间 func FormPut(cmd *cobra.Command, params []string) { bucket := params[0] key := params[1] @@ -183,6 +185,8 @@ func FormPut(cmd *cobra.Command, params []string) { } } +// 使用分片上传本地文件到七牛存储空间, 一般用于较大文件的上传 +// 文件会被分割成4M大小的块, 一块一块地上传文件 func ResumablePut(cmd *cobra.Command, params []string) { bucket := params[0] key := params[1] diff --git a/cmd/qdownload.go b/cmd/qdownload.go index 2220aba9..29801555 100644 --- a/cmd/qdownload.go +++ b/cmd/qdownload.go @@ -12,7 +12,7 @@ import ( ) var qDownloadCmd = &cobra.Command{ - Use: "qdownload [] ", + Use: "qdownload [-c ] ", Short: "Batch download files from the qiniu bucket", Long: "By default qdownload use 5 goroutines to download, it can be customized use -c flag", Args: cobra.ExactArgs(1), @@ -29,6 +29,9 @@ func init() { RootCmd.AddCommand(qDownloadCmd) } +// 【qdownload】下载七牛存储空间中的文件 +// 可以根据文件前缀下载符合要求的所有文件,也可以用户给到要下载的文件名字列表下载文件 +// 根据文件列表下载文件功能在文档中还没有公开,遇到有这个需求的客户比较少 func QiniuDownload(cmd *cobra.Command, params []string) { var downloadConfig iqshell.DownloadConfig diff --git a/cmd/qupload.go b/cmd/qupload.go index 59cf0ee6..695fdf03 100644 --- a/cmd/qupload.go +++ b/cmd/qupload.go @@ -66,7 +66,8 @@ func parseUploadConfigFile(uploadConfigFile string, uploadConfig *iqshell.Upload return } -// upload cmd +// [qupload]命令, 上传本地文件到七牛存储中 +// 该命令会读取配置文件, 上传本地文件系统的文件到七牛存储中; 可以设置多线程上传,默认的线程区间在[iqshell.MIN_UPLOAD_THREAD_COUNT, iqshell.MAX_UPLOAD_THREAD_COUNT] func QiniuUpload(cmd *cobra.Command, params []string) { configFile := params[0] diff --git a/cmd/qupload2.go b/cmd/qupload2.go index 5a1f46b0..46e2559d 100644 --- a/cmd/qupload2.go +++ b/cmd/qupload2.go @@ -56,6 +56,7 @@ func init() { RootCmd.AddCommand(qUpload2Cmd) } +// 【qupload2】和命令【qupload】的功能一样,只是使用的是命令选项的方式提供配置信息 func QiniuUpload2(cmd *cobra.Command, params []string) { //check params diff --git a/cmd/root.go b/cmd/root.go index d8b003bf..fb0f7c39 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -9,15 +9,17 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" "os" - "os/user" "path/filepath" "runtime" "strings" ) var ( - DebugFlag bool // debug flag - VersionFlag bool // version flag + // 开启命令行的调试模式 + DebugFlag bool + + // qshell 版本信息, qshell -v + VersionFlag bool cfgFile string local bool ) @@ -53,7 +55,7 @@ __custom_func() { ` ) -// cobra root cmd +// cobra root cmd, all other commands is children or subchildren of this root cmd var RootCmd = &cobra.Command{ Use: "qshell", Short: "Qiniu commandline tool for managing your bucket and CDN", @@ -96,12 +98,12 @@ func initConfig() { } viper.SetConfigFile(jsonConfigFile) } else { - curUser, gErr := user.Current() - if gErr != nil { - fmt.Fprintf(os.Stderr, "get current user: %v\n", gErr) + homeDir, hErr := homedir.Dir() + if hErr != nil { + fmt.Fprintf(os.Stderr, "get current home directory: %v\n", hErr) os.Exit(1) } - viper.AddConfigPath(curUser.HomeDir) + viper.AddConfigPath(homeDir) viper.SetConfigName(".qshell") } diff --git a/cmd/rs.go b/cmd/rs.go index 6dd1b63e..1637e9f4 100644 --- a/cmd/rs.go +++ b/cmd/rs.go @@ -164,6 +164,7 @@ func init() { saveAsCmd, m3u8DelCmd, m3u8RepCmd, privateUrlCmd, lsBucketCmd2) } +// 【dircache】扫描本地文件目录, 形成一个关于文件信息的文本文件 func DirCache(cmd *cobra.Command, params []string) { var cacheResultFile string cacheRootPath := params[0] @@ -178,6 +179,7 @@ func DirCache(cmd *cobra.Command, params []string) { } } +// 【listbucket2】 使用v2接口列举存储空间中的文件 func ListBucket2(cmd *cobra.Command, params []string) { bucket := params[0] @@ -226,6 +228,7 @@ func ListBucket2(cmd *cobra.Command, params []string) { } } +// 【listbucket】列举七牛存储空间中的文件列表 func ListBucket(cmd *cobra.Command, params []string) { bucket := params[0] @@ -236,6 +239,7 @@ func ListBucket(cmd *cobra.Command, params []string) { } } +// 【get】下载七牛存储中的一个文件, 该命令不需要存储空间绑定有可访问的CDN域名 func Get(cmd *cobra.Command, params []string) { bucket := params[0] @@ -254,6 +258,7 @@ func Get(cmd *cobra.Command, params []string) { } } +// 【stat】获取文件的meta信息,包括文件名字,hash, 上传时间,文件大小等信息 func Stat(cmd *cobra.Command, params []string) { bucket := params[0] key := params[1] @@ -268,6 +273,7 @@ func Stat(cmd *cobra.Command, params []string) { } } +// 【delete】删除七牛存储空间中的文件 func Delete(cmd *cobra.Command, params []string) { bucket := params[0] key := params[1] @@ -280,6 +286,7 @@ func Delete(cmd *cobra.Command, params []string) { } } +// 【move】 移动一个七牛存储空间的文件到另一个七牛的存储空间,该命令只适用于同属一个存储区域的存储空间中的文件 func Move(cmd *cobra.Command, params []string) { srcBucket := params[0] srcKey := params[1] @@ -297,6 +304,7 @@ func Move(cmd *cobra.Command, params []string) { } } +// 【copy】拷贝一个七牛存储空间的文件到另一个七牛的存储空间,该命令只适用于同属一个存储区域的存储空间中的文件 func Copy(cmd *cobra.Command, params []string) { srcBucket := params[0] srcKey := params[1] @@ -313,6 +321,7 @@ func Copy(cmd *cobra.Command, params []string) { } } +// 【chtype】改变七牛存储空间的文件的MimeType func Chgm(cmd *cobra.Command, params []string) { bucket := params[0] key := params[1] @@ -326,6 +335,7 @@ func Chgm(cmd *cobra.Command, params []string) { } } +// 【chtype】改变文件的存储类型,在七牛中存储的文件分为标准存储和低频存储 func Chtype(cmd *cobra.Command, params []string) { bucket := params[0] key := params[1] @@ -345,6 +355,7 @@ func Chtype(cmd *cobra.Command, params []string) { } } +// 【expire】给存储在七牛空间中的文件设置删除属性,设置以后,到指定时间会自动删除该文件 func DeleteAfterDays(cmd *cobra.Command, params []string) { bucket := params[0] key := params[1] @@ -364,6 +375,7 @@ func DeleteAfterDays(cmd *cobra.Command, params []string) { } } +// 【fetch】通过http链接抓取网上的资源到七牛存储空间 func Fetch(cmd *cobra.Command, params []string) { remoteResUrl := params[0] bucket := params[1] @@ -390,6 +402,7 @@ func Fetch(cmd *cobra.Command, params []string) { } } +// 【cdnprefetch】CDN文件预取, 预取文件到CDN节点和父层节点 func Prefetch(cmd *cobra.Command, params []string) { bucket := params[0] key := params[1] @@ -402,6 +415,7 @@ func Prefetch(cmd *cobra.Command, params []string) { } } +// 【saveas】打印输出主动saveas链接 func Saveas(cmd *cobra.Command, params []string) { publicUrl := params[0] saveBucket := params[1] @@ -417,6 +431,7 @@ func Saveas(cmd *cobra.Command, params []string) { } } +// 【m3u8delete】删除m3u8文件,包括m3u8文件本身和分片文件 func M3u8Delete(cmd *cobra.Command, params []string) { bucket := params[0] m3u8Key := params[1] @@ -452,6 +467,7 @@ func M3u8Delete(cmd *cobra.Command, params []string) { } } +// 【m3u8replace】替换m3u8文件中的域名信息 func M3u8Replace(cmd *cobra.Command, params []string) { bucket := params[0] m3u8Key := params[1] @@ -468,6 +484,7 @@ func M3u8Replace(cmd *cobra.Command, params []string) { } } +// 【privateurl】打印七牛私有空间的文件的下载链接(私有空间的文件下载去要鉴权验证) func PrivateUrl(cmd *cobra.Command, params []string) { publicUrl := params[0] var deadline int64 diff --git a/cmd/rsbatch.go b/cmd/rsbatch.go index d60ff179..75e518b4 100644 --- a/cmd/rsbatch.go +++ b/cmd/rsbatch.go @@ -165,6 +165,7 @@ func init() { batchRenameCmd, batchMoveCmd, batchCopyCmd, batchSignCmd, batchFetchCmd) } +// 批量抓取网络资源到七牛存储空间 func BatchFetch(cmd *cobra.Command, params []string) { if worker <= 0 || worker > 1000 { fmt.Fprintf(os.Stderr, "threads count: %d is too large, must be (0, 1000]", worker) @@ -260,6 +261,7 @@ func batchFetch(fItemChan chan *iqshell.FetchItem, fileExporter *iqshell.FileExp } } +// 批量获取文件列表的信息 func BatchStat(cmd *cobra.Command, params []string) { bucket := params[0] @@ -332,6 +334,7 @@ func batchStat(entries []iqshell.EntryPath, bm *iqshell.BucketManager) { } } +// 批量删除七牛存储空间中的文件 func BatchDelete(cmd *cobra.Command, params []string) { if !forceFlag { //confirm @@ -455,6 +458,7 @@ func batchDelete(entries []iqshell.EntryPath, bm *iqshell.BucketManager, fileExp } } +// 批量修改存储在七牛存储空间中文件的MimeType信息 func BatchChgm(cmd *cobra.Command, params []string) { if !forceFlag { //confirm @@ -576,6 +580,7 @@ func batchChgm(entries []iqshell.ChgmEntryPath, bm *iqshell.BucketManager, fileE } } +// 批量修改存储在七牛存储空间中文件的存储类型信息(标准存储-》低频存储,低频-》标准存储) func BatchChtype(cmd *cobra.Command, params []string) { if !forceFlag { //confirm @@ -708,6 +713,7 @@ func batchChtype(entries []iqshell.ChtypeEntryPath, bm *iqshell.BucketManager, f return } +// 批量设置七牛存储空间中的删除标志(多少天后删除) func BatchDeleteAfterDays(cmd *cobra.Command, params []string) { if !forceFlag { //confirm @@ -823,6 +829,7 @@ func batchDeleteAfterDays(entries []iqshell.DeleteAfterDaysEntryPath, bm *iqshel } } +// 批量重命名七牛存储空间中的文件 func BatchRename(cmd *cobra.Command, params []string) { if !forceFlag { //confirm @@ -950,6 +957,7 @@ func batchRename(entries []iqshell.RenameEntryPath, bm *iqshell.BucketManager, f } } +// 批量移动七牛存储空间中的文件 func BatchMove(cmd *cobra.Command, params []string) { if !forceFlag { //confirm @@ -1087,6 +1095,7 @@ func batchMove(entries []iqshell.MoveEntryPath, bm *iqshell.BucketManager, fileE } } +// 批量拷贝七牛存储中的文件 func BatchCopy(cmd *cobra.Command, params []string) { if !forceFlag { //confirm @@ -1226,6 +1235,7 @@ func batchCopy(entries []iqshell.CopyEntryPath, bm *iqshell.BucketManager, fileE } } +// 批量签名存储空间中的文件 func BatchSign(cmd *cobra.Command, params []string) { if deadline <= 0 { fmt.Fprintf(os.Stderr, "Invalid : deadline must be int and greater than 0\n") diff --git a/cmd/sync.go b/cmd/sync.go index ef557f61..381d6acf 100644 --- a/cmd/sync.go +++ b/cmd/sync.go @@ -27,6 +27,8 @@ func init() { RootCmd.AddCommand(syncCmd) } +// 抓取网络中的资源到七牛存储空间,使用与比较大的文件 +// 小文件抓取可以使用fetch接口, qshell fetch命令 func Sync(cmd *cobra.Command, params []string) { srcResUrl := params[0] bucket := params[1] diff --git a/cmd/token.go b/cmd/token.go index 94221517..3808421b 100644 --- a/cmd/token.go +++ b/cmd/token.go @@ -101,6 +101,7 @@ func macRequest(ak, sk, url, body, contentType, method string) (mac *qbox.Mac, r return } +// QBox Token, 一般bucket相关的接口需要这个token func QBoxToken(cmd *cobra.Command, args []string) { mac, req, mErr := macRequest(ak, sk, args[0], httpBody, contentType, "") if mErr != nil { @@ -115,6 +116,7 @@ func QBoxToken(cmd *cobra.Command, args []string) { fmt.Println("QBox " + token) } +// 签名七牛token, 一般三鉴接口需要http头文件 Authorization, 这个头的值就是qiniuToken func QiniuToken(cmd *cobra.Command, args []string) { mac, req, mErr := macRequest(ak, sk, args[0], httpBody, contentType, method) @@ -130,6 +132,7 @@ func QiniuToken(cmd *cobra.Command, args []string) { fmt.Println("Qiniu " + token) } +// 给定上传策略,打印出上传token func UploadToken(cmd *cobra.Command, args []string) { fileName := args[0] diff --git a/cmd/utils.go b/cmd/utils.go index 5fa23e20..fbbc0fc0 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -15,6 +15,7 @@ import ( ) const ( + // ASCII英文字母 ALPHA_LIST = "abcdefghijklmnopqrstuvwxyz" ) @@ -126,6 +127,7 @@ func init() { d2tsCmd, urlEcmd, urlDcmd, etagCmd, unzipCmd, reqidCmd) } +// 转化文件大小到人工可读的字符串,以相应的单位显示 func FormatFsize(fsize int64) (result string) { if fsize > TB { result = fmt.Sprintf("%.2f TB", float64(fsize)/float64(TB)) @@ -165,6 +167,7 @@ func RpcEncode(cmd *cobra.Command, params []string) { } } +// base64编码数据 func Base64Encode(cmd *cobra.Command, params []string) { dataToEncode := params[0] dataEncoded := "" @@ -176,6 +179,7 @@ func Base64Encode(cmd *cobra.Command, params []string) { fmt.Println(dataEncoded) } +// 解码base64编码的数据 func Base64Decode(cmd *cobra.Command, params []string) { var err error @@ -197,6 +201,7 @@ func Base64Decode(cmd *cobra.Command, params []string) { fmt.Println(string(dataDecoded)) } +// 转化unix时间戳为可读的字符串 func Timestamp2Date(cmd *cobra.Command, params []string) { ts, err := strconv.ParseInt(params[0], 10, 64) if err != nil { @@ -207,6 +212,7 @@ func Timestamp2Date(cmd *cobra.Command, params []string) { fmt.Println(t.String()) } +// 转化纳秒时间戳到人工可读的字符串 func TimestampNano2Date(cmd *cobra.Command, params []string) { tns, err := strconv.ParseInt(params[0], 10, 64) if err != nil { @@ -217,6 +223,7 @@ func TimestampNano2Date(cmd *cobra.Command, params []string) { fmt.Println(t.String()) } +// 转化毫秒时间戳到人工可读的字符串 func TimestampMilli2Date(cmd *cobra.Command, params []string) { tms, err := strconv.ParseInt(params[0], 10, 64) if err != nil { @@ -227,6 +234,7 @@ func TimestampMilli2Date(cmd *cobra.Command, params []string) { fmt.Println(t.String()) } +// 转化时间字符串到unix时间戳 func Date2Timestamp(cmd *cobra.Command, params []string) { secs, err := strconv.ParseInt(params[0], 10, 64) if err != nil { @@ -254,6 +262,7 @@ func Urldecode(cmd *cobra.Command, params []string) { } } +// 计算文件的hash值,使用七牛的etag算法 func Qetag(cmd *cobra.Command, params []string) { localFilePath := params[0] qetag, err := iqshell.GetEtag(localFilePath) @@ -264,6 +273,7 @@ func Qetag(cmd *cobra.Command, params []string) { fmt.Println(qetag) } +// 解压使用mkzip压缩的文件 func Unzip(cmd *cobra.Command, params []string) { zipFilePath := params[0] var err error @@ -285,6 +295,7 @@ func Unzip(cmd *cobra.Command, params []string) { } } +// 解析reqid, 打印人工可读的字符串 func ReqId(cmd *cobra.Command, params []string) { reqId := params[0] decodedBytes, err := base64.URLEncoding.DecodeString(reqId) @@ -309,6 +320,7 @@ func ReqId(cmd *cobra.Command, params []string) { dstDate.Hour(), dstDate.Minute())) } +// 生成随机的字符串 func CreateRandString(num int) (rcode string) { if num <= 0 || num > len(ALPHA_LIST) { rcode = "" diff --git a/cmd/version.go b/cmd/version.go index 67b5f536..70d28fea 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -20,6 +20,7 @@ func init() { RootCmd.AddCommand(versionCmd) } +// 生成客户端代理名称 func UserAgent() string { return fmt.Sprintf("QShell/%s (%s; %s; %s)", version, runtime.GOOS, runtime.GOARCH, runtime.Version()) } diff --git a/iqshell/alioss_list_bucket.go b/iqshell/alioss_list_bucket.go index c3686e2a..d34ea94a 100644 --- a/iqshell/alioss_list_bucket.go +++ b/iqshell/alioss_list_bucket.go @@ -8,6 +8,7 @@ import ( "os" ) +// 阿里空间字段 type AliListBucket struct { DataCenter string AccessKeyId string @@ -16,6 +17,7 @@ type AliListBucket struct { Prefix string } +// 列举阿里空间的文件列表 func (this *AliListBucket) ListBucket(listResultFile string) (err error) { //open result file fp, openErr := os.Create(listResultFile) diff --git a/iqshell/bucket.go b/iqshell/bucket.go index 2ccecbd2..66dbf54b 100644 --- a/iqshell/bucket.go +++ b/iqshell/bucket.go @@ -71,6 +71,7 @@ type BucketDomainsRet []struct { Owner int `json:"owner"` } +// 获取一个存储空间绑定的CDN域名 func (m *BucketManager) DomainsOfBucket(bucket string) (domains []string, err error) { ctx := context.WithValue(context.TODO(), "mac", m.Mac) var reqHost string @@ -96,6 +97,7 @@ func (m *BucketManager) DomainsOfBucket(bucket string) (domains []string, err er } +// 返回私有空间的下载链接, 也可以用于公有空间的下载 func (m *BucketManager) MakePrivateDownloadLink(domainOfBucket, fileKey string) (fileUrl string) { publicUrl := fmt.Sprintf("http://%s/%s", domainOfBucket, url.PathEscape(fileKey)) @@ -105,6 +107,7 @@ func (m *BucketManager) MakePrivateDownloadLink(domainOfBucket, fileKey string) return } +// 返回私有空间的下载链接, 也可以用于公有空间的下载 func (m *BucketManager) PrivateUrl(publicUrl string, deadline int64) (finalUrl string, err error) { srcUri, pErr := url.Parse(publicUrl) if pErr != nil { @@ -142,6 +145,7 @@ func (m *BucketManager) rsHost(bucket string) (rsHost string, err error) { return } +// 从存储空间下载文件(不需要绑定CDN域名) func (m *BucketManager) Get(bucket, key string, destFile string) (err error) { entryUri := strings.Join([]string{bucket, key}, ":") diff --git a/iqshell/config.go b/iqshell/config.go index c5f3bd90..ec9dd087 100644 --- a/iqshell/config.go +++ b/iqshell/config.go @@ -16,20 +16,40 @@ const ( ) const ( - BLOCK_BITS = 22 // Indicate that the blocksize is 4M - BLOCK_SIZE = 1 << BLOCK_BITS // BLOCK SIZE + // Indicate that the blocksize is 4M + BLOCK_BITS = 22 + + // BLOCK SIZE + BLOCK_SIZE = 1 << BLOCK_BITS ) var ( - PATH_ROOT = []string{"path.root", "path.root_path"} // qshell的工作根目录 - PATH_ACCDB = []string{"path.accdb", "path.acc_db_path"} // qshell本地数据库文件目录 - PATH_ACC = []string{"path.acc", "path.acc_path"} // qshell 账户文件目录 - HOST_UP = []string{"hosts.up", "hosts.up_host"} // 上传HOST - HOST_RS = []string{"hosts.rs", "hosts.rs_host"} // RS HOST - HOST_RSF = []string{"hosts.rsf", "hosts.rsf_host"} // RSF HOST - HOST_IO = []string{"hosts.io", "hosts.io_host"} // IO HOST - HOST_API = []string{"hosts.api", "hosts.api_host"} // API HOST - ACCESS_KEY = []string{"access_key"} // 账户密钥信息 + // qshell的工作根目录 + PATH_ROOT = []string{"path.root", "path.root_path"} + + // qshell本地数据库文件目录 + PATH_ACCDB = []string{"path.accdb", "path.acc_db_path"} + + // qshell 账户文件目录 + PATH_ACC = []string{"path.acc", "path.acc_path"} + + // 上传HOST + HOST_UP = []string{"hosts.up", "hosts.up_host"} + + // RS HOST + HOST_RS = []string{"hosts.rs", "hosts.rs_host"} + + // RSF HOST + HOST_RSF = []string{"hosts.rsf", "hosts.rsf_host"} + + // IO HOST + HOST_IO = []string{"hosts.io", "hosts.io_host"} + + // API HOST + HOST_API = []string{"hosts.api", "hosts.api_host"} + + // 账户密钥信息 + ACCESS_KEY = []string{"access_key"} SECRET_KEY = []string{"secret_key"} ) diff --git a/iqshell/crypto.go b/iqshell/crypto.go index 13b15df8..8117b241 100644 --- a/iqshell/crypto.go +++ b/iqshell/crypto.go @@ -8,12 +8,14 @@ import ( "encoding/hex" ) +// 字符串的md5值 func Md5Hex(from string) string { md5Hasher := md5.New() md5Hasher.Write([]byte(from)) return hex.EncodeToString(md5Hasher.Sum(nil)) } +// 加密数据 func AesEncrypt(origData, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { @@ -27,6 +29,7 @@ func AesEncrypt(origData, key []byte) ([]byte, error) { return crypted, nil } +// 解密数据 func AesDecrypt(crypted, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { @@ -41,12 +44,14 @@ func AesDecrypt(crypted, key []byte) ([]byte, error) { return origData, nil } +// 加密解密需要数据一定的格式, 如果愿数据不符合要求,需要加一些padding func PKCS5Padding(ciphertext []byte, blockSize int) []byte { padding := blockSize - len(ciphertext)%blockSize padtext := bytes.Repeat([]byte{byte(padding)}, padding) return append(ciphertext, padtext...) } +// 加密解密需要数据一定的格式, 如果愿数据不符合要求,需要加一些padding func PKCS5UnPadding(origData []byte) []byte { length := len(origData) unpadding := int(origData[length-1]) diff --git a/iqshell/qdownload.go b/iqshell/qdownload.go index b0b6b0d5..882417d4 100644 --- a/iqshell/qdownload.go +++ b/iqshell/qdownload.go @@ -29,10 +29,11 @@ import ( */ const ( - MIN_DOWNLOAD_THREAD_COUNT = 1 - MAX_DOWNLOAD_THREAD_COUNT = 2000 + MIN_DOWNLOAD_THREAD_COUNT = 1 // 最小的下载线程数目 + MAX_DOWNLOAD_THREAD_COUNT = 2000 // 最大下载线程数目 ) +// qdownload子命令用到的配置参数 type DownloadConfig struct { FileEncoding string `json:"file_encoding"` KeyFile string `json:"key_file"` @@ -51,6 +52,7 @@ type DownloadConfig struct { LogStdout bool `json:"log_stdout,omitempty"` } +// 获取一个存储空间的绑定的所有域名 func (d *DownloadConfig) DomainOfBucket(bm *BucketManager) (domain string, err error) { //get domains of bucket domainsOfBucket, gErr := bm.DomainsOfBucket(d.Bucket) @@ -73,6 +75,7 @@ func (d *DownloadConfig) DomainOfBucket(bm *BucketManager) (domain string, err e return } +// 获取一个存储空间的下载域名, 默认使用用户配置的域名,如果没有就使用接口随机选择一个下载域名 func (d *DownloadConfig) DownloadDomain(domainOfBucket string) (domain string) { if d.CdnDomain != "" { domain = d.CdnDomain @@ -97,6 +100,7 @@ func doDownload(tasks chan func()) { } } +// 【qdownload] 批量下载文件, 可以下载以前缀的文件,也可以下载一个文件列表 func QiniuDownload(threadCount int, downConfig *DownloadConfig) { QShellRootPath := RootPath() if QShellRootPath == "" { @@ -205,16 +209,23 @@ func QiniuDownload(threadCount int, downConfig *DownloadConfig) { } entries = append(entries, entry) } - batches := len(entries)/1000 + 1 + + var batches int + if len(entries)%1000 == 0 { + batches = len(entries) / 1000 + } else { + batches = len(entries)/1000 + 1 + } for i := 0; i < batches; i++ { - ret, err := bm.BatchStat(entries) + childEntries := entries[i*1000 : i*1000+1000] + ret, err := bm.BatchStat(childEntries) if err != nil { fmt.Fprintf(os.Stderr, "Batch stat error: %v\n", err) os.Exit(STATUS_ERROR) } - if len(ret) > 0 { - for i, entry := range entries { - item := ret[i] + if len(childEntries) == len(ret) { + for j, entry := range childEntries { + item := ret[j] if item.Code != 200 || item.Data.Error != "" { fmt.Fprintln(os.Stderr, entry.Key+"\t"+item.Data.Error) } else {