upload.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. package command
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "os"
  7. "path/filepath"
  8. "github.com/seaweedfs/seaweedfs/weed/pb"
  9. "github.com/seaweedfs/seaweedfs/weed/pb/master_pb"
  10. "google.golang.org/grpc"
  11. "github.com/seaweedfs/seaweedfs/weed/operation"
  12. "github.com/seaweedfs/seaweedfs/weed/security"
  13. "github.com/seaweedfs/seaweedfs/weed/util"
  14. )
  15. var (
  16. upload UploadOptions
  17. )
  18. type UploadOptions struct {
  19. master *string
  20. dir *string
  21. include *string
  22. replication *string
  23. collection *string
  24. dataCenter *string
  25. ttl *string
  26. diskType *string
  27. maxMB *int
  28. usePublicUrl *bool
  29. }
  30. func init() {
  31. cmdUpload.Run = runUpload // break init cycle
  32. cmdUpload.IsDebug = cmdUpload.Flag.Bool("debug", false, "verbose debug information")
  33. upload.master = cmdUpload.Flag.String("master", "localhost:9333", "SeaweedFS master location")
  34. upload.dir = cmdUpload.Flag.String("dir", "", "Upload the whole folder recursively if specified.")
  35. upload.include = cmdUpload.Flag.String("include", "", "pattens of files to upload, e.g., *.pdf, *.html, ab?d.txt, works together with -dir")
  36. upload.replication = cmdUpload.Flag.String("replication", "", "replication type")
  37. upload.collection = cmdUpload.Flag.String("collection", "", "optional collection name")
  38. upload.dataCenter = cmdUpload.Flag.String("dataCenter", "", "optional data center name")
  39. upload.diskType = cmdUpload.Flag.String("disk", "", "[hdd|ssd|<tag>] hard drive or solid state drive or any tag")
  40. upload.ttl = cmdUpload.Flag.String("ttl", "", "time to live, e.g.: 1m, 1h, 1d, 1M, 1y")
  41. upload.maxMB = cmdUpload.Flag.Int("maxMB", 4, "split files larger than the limit")
  42. upload.usePublicUrl = cmdUpload.Flag.Bool("usePublicUrl", false, "upload to public url from volume server")
  43. }
  44. var cmdUpload = &Command{
  45. UsageLine: "upload -master=localhost:9333 file1 [file2 file3]\n weed upload -master=localhost:9333 -dir=one_directory -include=*.pdf",
  46. Short: "upload one or a list of files",
  47. Long: `upload one or a list of files, or batch upload one whole folder recursively.
  48. If uploading a list of files:
  49. It uses consecutive file keys for the list of files.
  50. e.g. If the file1 uses key k, file2 can be read via k_1
  51. If uploading a whole folder recursively:
  52. All files under the folder and subfolders will be uploaded, each with its own file key.
  53. Optional parameter "-include" allows you to specify the file name patterns.
  54. If "maxMB" is set to a positive number, files larger than it would be split into chunks and uploaded separately.
  55. The list of file ids of those chunks would be stored in an additional chunk, and this additional chunk's file id would be returned.
  56. `,
  57. }
  58. func runUpload(cmd *Command, args []string) bool {
  59. util.LoadConfiguration("security", false)
  60. grpcDialOption := security.LoadClientTLS(util.GetViper(), "grpc.client")
  61. defaultReplication, err := readMasterConfiguration(grpcDialOption, pb.ServerAddress(*upload.master))
  62. if err != nil {
  63. fmt.Printf("upload: %v", err)
  64. return false
  65. }
  66. if *upload.replication == "" {
  67. *upload.replication = defaultReplication
  68. }
  69. if len(args) == 0 {
  70. if *upload.dir == "" {
  71. return false
  72. }
  73. err = filepath.Walk(util.ResolvePath(*upload.dir), func(path string, info os.FileInfo, err error) error {
  74. if err == nil {
  75. if !info.IsDir() {
  76. if *upload.include != "" {
  77. if ok, _ := filepath.Match(*upload.include, filepath.Base(path)); !ok {
  78. return nil
  79. }
  80. }
  81. parts, e := operation.NewFileParts([]string{path})
  82. if e != nil {
  83. return e
  84. }
  85. results, e := operation.SubmitFiles(func(_ context.Context) pb.ServerAddress { return pb.ServerAddress(*upload.master) }, grpcDialOption, parts, *upload.replication, *upload.collection, *upload.dataCenter, *upload.ttl, *upload.diskType, *upload.maxMB, *upload.usePublicUrl)
  86. bytes, _ := json.Marshal(results)
  87. fmt.Println(string(bytes))
  88. if e != nil {
  89. return e
  90. }
  91. }
  92. } else {
  93. fmt.Println(err)
  94. }
  95. return err
  96. })
  97. if err != nil {
  98. fmt.Println(err.Error())
  99. return false
  100. }
  101. } else {
  102. parts, e := operation.NewFileParts(args)
  103. if e != nil {
  104. fmt.Println(e.Error())
  105. return false
  106. }
  107. results, err := operation.SubmitFiles(func(_ context.Context) pb.ServerAddress { return pb.ServerAddress(*upload.master) }, grpcDialOption, parts, *upload.replication, *upload.collection, *upload.dataCenter, *upload.ttl, *upload.diskType, *upload.maxMB, *upload.usePublicUrl)
  108. if err != nil {
  109. fmt.Println(err.Error())
  110. return false
  111. }
  112. bytes, _ := json.Marshal(results)
  113. fmt.Println(string(bytes))
  114. }
  115. return true
  116. }
  117. func readMasterConfiguration(grpcDialOption grpc.DialOption, masterAddress pb.ServerAddress) (replication string, err error) {
  118. err = pb.WithMasterClient(false, masterAddress, grpcDialOption, false, func(client master_pb.SeaweedClient) error {
  119. resp, err := client.GetMasterConfiguration(context.Background(), &master_pb.GetMasterConfigurationRequest{})
  120. if err != nil {
  121. return fmt.Errorf("get master %s configuration: %v", masterAddress, err)
  122. }
  123. replication = resp.DefaultReplication
  124. return nil
  125. })
  126. return
  127. }