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.

geto.go 3.5 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. package geto
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. "path/filepath"
  7. "strconv"
  8. "time"
  9. "github.com/inhies/go-bytesize"
  10. "github.com/spf13/cobra"
  11. cliapi "gitlink.org.cn/cloudream/jcs-pub/client/sdk/api/v1"
  12. clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types"
  13. "gitlink.org.cn/cloudream/jcs-pub/jcsctl/cmd"
  14. )
  15. func init() {
  16. var opt option
  17. c := &cobra.Command{
  18. Use: "geto <bucket_name>/<package_name>:<object_path> <local_dir>",
  19. Short: "download object to local disk",
  20. Args: cobra.ExactArgs(2),
  21. RunE: func(c *cobra.Command, args []string) error {
  22. ctx := cmd.GetCmdCtx(c)
  23. return geto(c, ctx, opt, args)
  24. },
  25. }
  26. c.Flags().BoolVar(&opt.UseID, "id", false, "treat first argument as object id")
  27. c.Flags().Int64Var(&opt.Offset, "offset", 0, "offset of object to download")
  28. c.Flags().Int64Var(&opt.Length, "length", 0, "length of object to download")
  29. c.Flags().Int64Var(&opt.Seek, "seek", 0, "seek position when save to local file, if set, will not truncate local file")
  30. c.Flags().StringVarP(&opt.Output, "output", "o", "", "output file name")
  31. cmd.RootCmd.AddCommand(c)
  32. }
  33. type option struct {
  34. UseID bool
  35. Offset int64
  36. Length int64
  37. Seek int64
  38. Output string
  39. }
  40. func geto(c *cobra.Command, ctx *cmd.CommandContext, opt option, args []string) error {
  41. var obj clitypes.Object
  42. if opt.UseID {
  43. id, err := strconv.ParseInt(args[0], 10, 64)
  44. if err != nil {
  45. return fmt.Errorf("invalid object id: %v", err)
  46. }
  47. resp, err := ctx.Client.Object().ListByIDs(cliapi.ObjectListByIDs{
  48. ObjectIDs: []clitypes.ObjectID{clitypes.ObjectID(id)},
  49. })
  50. if err != nil {
  51. return fmt.Errorf("list objects by ids: %v", err)
  52. }
  53. if resp.Objects[0] == nil {
  54. return fmt.Errorf("object not found")
  55. }
  56. obj = *resp.Objects[0]
  57. } else {
  58. bkt, pkg, objPath, ok := cmd.SplitObjectPath(args[0])
  59. if !ok {
  60. return fmt.Errorf("invalid object path")
  61. }
  62. pkgResp, err := ctx.Client.Package().GetByFullName(cliapi.PackageGetByFullName{
  63. BucketName: bkt,
  64. PackageName: pkg,
  65. })
  66. if err != nil {
  67. return fmt.Errorf("get package by name: %v", err)
  68. }
  69. objResp, err := ctx.Client.Object().ListByPath(cliapi.ObjectListByPath{
  70. PackageID: pkgResp.Package.PackageID,
  71. Path: objPath,
  72. })
  73. if err != nil {
  74. return fmt.Errorf("list objects by path: %v", err)
  75. }
  76. if len(objResp.Objects) != 1 {
  77. return fmt.Errorf("object not found")
  78. }
  79. obj = objResp.Objects[0]
  80. }
  81. filePath := args[1]
  82. if opt.Output != "" {
  83. filePath = filepath.Join(filePath, opt.Output)
  84. } else {
  85. filePath = filepath.Join(filePath, clitypes.BaseName(obj.Path))
  86. }
  87. flag := os.O_CREATE | os.O_WRONLY
  88. if !c.Flags().Changed("seek") {
  89. flag |= os.O_TRUNC
  90. }
  91. file, err := os.OpenFile(filePath, flag, 0644)
  92. if err != nil {
  93. return fmt.Errorf("open file: %v", err)
  94. }
  95. defer file.Close()
  96. if opt.Seek != 0 {
  97. if _, err := file.Seek(opt.Seek, 0); err != nil {
  98. return fmt.Errorf("seek file: %v", err)
  99. }
  100. }
  101. fmt.Printf("%v\n", filePath)
  102. var len *int64
  103. if c.Flags().Changed("length") {
  104. len = &opt.Length
  105. }
  106. resp, err := ctx.Client.Object().Download(cliapi.ObjectDownload{
  107. ObjectID: obj.ObjectID,
  108. Offset: opt.Offset,
  109. Length: len,
  110. })
  111. if err != nil {
  112. return fmt.Errorf("download object: %v", err)
  113. }
  114. startTime := time.Now()
  115. n, err := io.Copy(file, resp.File)
  116. if err != nil {
  117. return fmt.Errorf("copy object to file: %v", err)
  118. }
  119. dt := time.Since(startTime)
  120. fmt.Printf("size: %v, time: %v, speed: %v/s\n", bytesize.ByteSize(n), dt, bytesize.ByteSize(int64(float64(n)/dt.Seconds())))
  121. return nil
  122. }

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