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.

putp.go 4.3 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. package putp
  2. import (
  3. "fmt"
  4. "os"
  5. "path"
  6. "path/filepath"
  7. "strconv"
  8. "strings"
  9. "time"
  10. "github.com/inhies/go-bytesize"
  11. "github.com/spf13/cobra"
  12. "gitlink.org.cn/cloudream/common/pkgs/iterator"
  13. "gitlink.org.cn/cloudream/common/sdks"
  14. cliapi "gitlink.org.cn/cloudream/jcs-pub/client/sdk/api/v1"
  15. clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types"
  16. "gitlink.org.cn/cloudream/jcs-pub/common/ecode"
  17. "gitlink.org.cn/cloudream/jcs-pub/jcsctl/cmd"
  18. )
  19. func init() {
  20. var opt option
  21. c := &cobra.Command{
  22. Use: "putp <local_path> <bucket_name>/<package_name>",
  23. Short: "upload local files to a package",
  24. Args: cobra.ExactArgs(2),
  25. RunE: func(c *cobra.Command, args []string) error {
  26. ctx := cmd.GetCmdCtx(c)
  27. return putp(c, ctx, opt, args)
  28. },
  29. }
  30. c.Flags().BoolVar(&opt.UseID, "id", false, "treat the second argument as package id")
  31. c.Flags().StringVar(&opt.Prefix, "prefix", "", "add prefix to every uploaded file")
  32. c.Flags().BoolVar(&opt.Create, "create", false, "create package if not exists")
  33. c.Flags().Int64Var(&opt.Affinity, "affinity", 0, "affinity user space of the package")
  34. cmd.RootCmd.AddCommand(c)
  35. }
  36. type option struct {
  37. UseID bool
  38. Prefix string
  39. Create bool
  40. Affinity int64
  41. }
  42. func putp(c *cobra.Command, ctx *cmd.CommandContext, opt option, args []string) error {
  43. absLocal, err := filepath.Abs(args[0])
  44. if err != nil {
  45. return err
  46. }
  47. local, err := os.Stat(absLocal)
  48. if err != nil {
  49. return err
  50. }
  51. var pkgID clitypes.PackageID
  52. if opt.UseID {
  53. id, err := strconv.ParseInt(args[1], 10, 64)
  54. if err != nil {
  55. return err
  56. }
  57. pkgID = clitypes.PackageID(id)
  58. _, err = ctx.Client.Package().Get(cliapi.PackageGet{
  59. PackageID: pkgID,
  60. })
  61. if err != nil {
  62. return err
  63. }
  64. } else {
  65. comps := strings.Split(args[1], "/")
  66. if len(comps) != 2 {
  67. return fmt.Errorf("invalid package name")
  68. }
  69. pkg, err := ctx.Client.Package().GetByFullName(cliapi.PackageGetByFullName{
  70. BucketName: comps[0],
  71. PackageName: comps[1],
  72. })
  73. if err != nil {
  74. if !sdks.IsErrorCode(err, string(ecode.DataNotFound)) {
  75. return err
  76. }
  77. if !opt.Create {
  78. return fmt.Errorf("package not found")
  79. }
  80. bkt, err := ctx.Client.Bucket().GetByName(cliapi.BucketGetByName{
  81. Name: comps[0],
  82. })
  83. if err != nil {
  84. return fmt.Errorf("get bucket %v: %w", comps[0], err)
  85. }
  86. cpkg, err := ctx.Client.Package().Create(cliapi.PackageCreate{
  87. BucketID: bkt.Bucket.BucketID,
  88. Name: comps[1],
  89. })
  90. if err != nil {
  91. return fmt.Errorf("create package %v: %w", args[1], err)
  92. }
  93. pkgID = cpkg.Package.PackageID
  94. } else {
  95. pkgID = pkg.Package.PackageID
  96. }
  97. }
  98. if !local.IsDir() {
  99. file, err := os.Open(absLocal)
  100. if err != nil {
  101. return err
  102. }
  103. defer file.Close()
  104. info, err := file.Stat()
  105. if err != nil {
  106. return err
  107. }
  108. pat := filepath.Base(absLocal)
  109. if opt.Prefix != "" {
  110. pat = path.Join(opt.Prefix, pat)
  111. }
  112. fmt.Printf("%v\n", pat)
  113. startTime := time.Now()
  114. _, err = ctx.Client.Object().Upload(cliapi.ObjectUpload{
  115. Info: cliapi.ObjectUploadInfo{
  116. PackageID: pkgID,
  117. Affinity: clitypes.UserSpaceID(opt.Affinity),
  118. },
  119. Files: iterator.Array(&cliapi.UploadingObject{
  120. Path: pat,
  121. File: file,
  122. }),
  123. })
  124. if err != nil {
  125. return fmt.Errorf("upload file %v: %w", pat, err)
  126. }
  127. dt := time.Since(startTime)
  128. fmt.Printf("size: %v, time: %v, speed: %v/s\n", bytesize.ByteSize(info.Size()), dt, bytesize.ByteSize(int64(float64(info.Size())/dt.Seconds())))
  129. return nil
  130. }
  131. iter := &FileIterator{
  132. absRootPath: absLocal,
  133. jpathRoot: clitypes.PathFromJcsPathString(opt.Prefix),
  134. }
  135. startTime := time.Now()
  136. _, err = ctx.Client.Object().Upload(cliapi.ObjectUpload{
  137. Info: cliapi.ObjectUploadInfo{
  138. PackageID: pkgID,
  139. Affinity: clitypes.UserSpaceID(opt.Affinity),
  140. },
  141. Files: iter,
  142. })
  143. if err != nil {
  144. if !iter.lastStartTime.IsZero() {
  145. fmt.Printf("\tx\n")
  146. }
  147. return fmt.Errorf("upload files: %w", err)
  148. }
  149. dt := time.Since(startTime)
  150. if !iter.lastStartTime.IsZero() {
  151. fileDt := time.Since(iter.lastStartTime)
  152. fmt.Printf("\t%v\n", fileDt)
  153. }
  154. fmt.Printf("%v files, total size: %v, time: %v, speed: %v/s\n", iter.fileCount, bytesize.ByteSize(iter.totalSize), dt, bytesize.ByteSize(int64(float64(iter.totalSize)/dt.Seconds())))
  155. return nil
  156. }

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