You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

getp.go 3.9 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. package getp
  2. import (
  3. "archive/tar"
  4. "fmt"
  5. "io"
  6. "os"
  7. "path/filepath"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "github.com/inhies/go-bytesize"
  12. "github.com/spf13/cobra"
  13. cliapi "gitlink.org.cn/cloudream/jcs-pub/client/sdk/api/v1"
  14. clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types"
  15. "gitlink.org.cn/cloudream/jcs-pub/jcsctl/cmd"
  16. )
  17. func init() {
  18. var opt option
  19. c := &cobra.Command{
  20. Use: "getp <bucket_name>/<package_name> <local_path>",
  21. Short: "download package all files to local disk",
  22. Args: cobra.ExactArgs(2),
  23. RunE: func(c *cobra.Command, args []string) error {
  24. ctx := cmd.GetCmdCtx(c)
  25. return getp(c, ctx, opt, args)
  26. },
  27. }
  28. c.Flags().BoolVar(&opt.UseID, "id", false, "treat first argument as package id")
  29. c.Flags().StringVar(&opt.Prefix, "prefix", "", "download objects with this prefix")
  30. c.Flags().StringVar(&opt.NewPrefix, "new", "", "replace prefix specified by --prefix with this prefix")
  31. c.Flags().BoolVar(&opt.Zip, "zip", false, "download as zip file")
  32. c.Flags().StringVarP(&opt.Output, "output", "o", "", "output zip file name")
  33. cmd.RootCmd.AddCommand(c)
  34. }
  35. type option struct {
  36. UseID bool
  37. Prefix string
  38. NewPrefix string
  39. Zip bool
  40. Output string
  41. }
  42. func getp(c *cobra.Command, ctx *cmd.CommandContext, opt option, args []string) error {
  43. var pkgID clitypes.PackageID
  44. if opt.UseID {
  45. id, err := strconv.ParseInt(args[0], 10, 64)
  46. if err != nil {
  47. return fmt.Errorf("invalid package id")
  48. }
  49. pkgID = clitypes.PackageID(id)
  50. } else {
  51. comps := strings.Split(args[0], "/")
  52. if len(comps) != 2 {
  53. return fmt.Errorf("invalid package name")
  54. }
  55. resp, err := ctx.Client.Package().GetByFullName(cliapi.PackageGetByFullName{
  56. BucketName: comps[0],
  57. PackageName: comps[1],
  58. })
  59. if err != nil {
  60. return fmt.Errorf("get package by name: %w", err)
  61. }
  62. pkgID = resp.Package.PackageID
  63. }
  64. info, err := os.Stat(args[1])
  65. if err != nil {
  66. return err
  67. }
  68. if !info.IsDir() {
  69. return fmt.Errorf("local path should be a directory")
  70. }
  71. req := cliapi.PackageDownload{
  72. PackageID: pkgID,
  73. Prefix: opt.Prefix,
  74. }
  75. if c.Flags().Changed("new") {
  76. req.NewPrefix = &opt.NewPrefix
  77. }
  78. if opt.Zip {
  79. req.Zip = true
  80. }
  81. downResp, err := ctx.Client.Package().Download(req)
  82. if err != nil {
  83. return fmt.Errorf("download package: %w", err)
  84. }
  85. defer downResp.File.Close()
  86. if opt.Zip {
  87. fileName := downResp.Name
  88. if opt.Output != "" {
  89. fileName = opt.Output
  90. }
  91. localFilePath := filepath.Join(args[1], fileName)
  92. file, err := os.OpenFile(localFilePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
  93. if err != nil {
  94. return err
  95. }
  96. fmt.Printf("%v\n", localFilePath)
  97. startTime := time.Now()
  98. n, err := io.Copy(file, downResp.File)
  99. if err != nil {
  100. return err
  101. }
  102. dt := time.Since(startTime)
  103. fmt.Printf("size: %v, time: %v, speed: %v/s\n", bytesize.ByteSize(n), dt, bytesize.ByteSize(int64(float64(n)/dt.Seconds())))
  104. return nil
  105. }
  106. startTime := time.Now()
  107. totalSize := int64(0)
  108. fileCnt := 0
  109. tr := tar.NewReader(downResp.File)
  110. for {
  111. header, err := tr.Next()
  112. if err == io.EOF {
  113. break
  114. }
  115. if err != nil {
  116. return err
  117. }
  118. localPath := filepath.Join(args[1], header.Name)
  119. fmt.Printf("%v", localPath)
  120. dir := filepath.Dir(localPath)
  121. err = os.MkdirAll(dir, 0755)
  122. if err != nil {
  123. fmt.Printf("\tx")
  124. return err
  125. }
  126. fileStartTime := time.Now()
  127. file, err := os.OpenFile(localPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
  128. if err != nil {
  129. fmt.Printf("\tx")
  130. return err
  131. }
  132. _, err = io.Copy(file, tr)
  133. if err != nil {
  134. fmt.Printf("\tx")
  135. return err
  136. }
  137. dt := time.Since(fileStartTime)
  138. fmt.Printf("\t%v\t%v\n", bytesize.ByteSize(header.Size), dt)
  139. fileCnt++
  140. totalSize += header.Size
  141. }
  142. dt := time.Since(startTime)
  143. fmt.Printf("%v files, total size: %v, time: %v, speed: %v/s\n", fileCnt, bytesize.ByteSize(totalSize), dt, bytesize.ByteSize(int64(float64(totalSize)/dt.Seconds())))
  144. return nil
  145. }

本项目旨在将云际存储公共基础设施化,使个人及企业可低门槛使用高效的云际存储服务(安装开箱即用云际存储客户端即可,无需关注其他组件的部署),同时支持用户灵活便捷定制云际存储的功能细节。