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

100 lines
2.6 KiB

  1. package main
  2. import (
  3. "code.google.com/p/weed-fs/go/operation"
  4. "code.google.com/p/weed-fs/go/util"
  5. "fmt"
  6. "io"
  7. "io/ioutil"
  8. "os"
  9. "path"
  10. "strings"
  11. )
  12. var (
  13. downloadReplication *string
  14. downloadDir *string
  15. )
  16. func init() {
  17. cmdDownload.Run = runDownload // break init cycle
  18. cmdDownload.IsDebug = cmdDownload.Flag.Bool("debug", false, "verbose debug information")
  19. server = cmdDownload.Flag.String("server", "localhost:9333", "weedfs master location")
  20. downloadDir = cmdDownload.Flag.String("dir", ".", "Download the whole folder recursively if specified.")
  21. }
  22. var cmdDownload = &Command{
  23. UsageLine: "download -server=localhost:9333 -dir=one_directory fid1 [fid2 fid3 ...]",
  24. Short: "download files by file id",
  25. Long: `download files by file id.
  26. Usually you just need to use curl to lookup the file's volume server, and then download them directly.
  27. This download tool combine the two steps into one.
  28. What's more, if you use "weed upload -maxMB=..." option to upload a big file divided into chunks, you can
  29. use this tool to download the chunks and merge them automatically.
  30. `,
  31. }
  32. func runDownload(cmd *Command, args []string) bool {
  33. for _, fid := range args {
  34. filename, content, e := fetchFileId(*server, fid)
  35. if e != nil {
  36. fmt.Println("Fetch Error:", e)
  37. continue
  38. }
  39. if filename == "" {
  40. filename = fid
  41. }
  42. if strings.HasSuffix(filename, "-list") {
  43. filename = filename[0 : len(filename)-len("-list")]
  44. fids := strings.Split(string(content), "\n")
  45. f, err := os.OpenFile(path.Join(*downloadDir, filename), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm)
  46. if err != nil {
  47. fmt.Println("File Creation Error:", e)
  48. continue
  49. }
  50. defer f.Close()
  51. for _, partId := range fids {
  52. var n int
  53. _, part, err := fetchFileId(*server, partId)
  54. if err == nil {
  55. n, err = f.Write(part)
  56. }
  57. if err == nil && n < len(part) {
  58. err = io.ErrShortWrite
  59. }
  60. if err != nil {
  61. fmt.Println("File Write Error:", err)
  62. break
  63. }
  64. }
  65. } else {
  66. ioutil.WriteFile(path.Join(*downloadDir, filename), content, os.ModePerm)
  67. }
  68. }
  69. return true
  70. }
  71. func fetchFileId(server string, fileId string) (filename string, content []byte, e error) {
  72. fileUrl, lookupError := operation.LookupFileId(server, fileId)
  73. if lookupError != nil {
  74. return "", nil, lookupError
  75. }
  76. filename, content, e = util.DownloadUrl(fileUrl)
  77. return
  78. }
  79. func WriteFile(filename string, data []byte, perm os.FileMode) error {
  80. f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
  81. if err != nil {
  82. return err
  83. }
  84. n, err := f.Write(data)
  85. f.Close()
  86. if err == nil && n < len(data) {
  87. err = io.ErrShortWrite
  88. }
  89. return err
  90. }