From ac66eee045e5670f3578717a90d6c0069977c06e Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Mon, 18 Nov 2013 23:41:00 -0800 Subject: [PATCH] added download command to download file by fileid --- go/weed/download.go | 120 ++++++++++++++++++++++++++++++++++++++++++++ go/weed/weed.go | 3 +- 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 go/weed/download.go diff --git a/go/weed/download.go b/go/weed/download.go new file mode 100644 index 000000000..4f332bd2e --- /dev/null +++ b/go/weed/download.go @@ -0,0 +1,120 @@ +package main + +import ( + "code.google.com/p/weed-fs/go/glog" + "code.google.com/p/weed-fs/go/operation" + "fmt" + "io" + "io/ioutil" + "net/http" + "os" + "path" + "strings" +) + +var ( + downloadReplication *string + downloadDir *string +) + +func init() { + cmdDownload.Run = runDownload // break init cycle + cmdDownload.IsDebug = cmdDownload.Flag.Bool("debug", false, "verbose debug information") + server = cmdDownload.Flag.String("server", "localhost:9333", "weedfs master location") + downloadDir = cmdDownload.Flag.String("dir", ".", "Download the whole folder recursively if specified.") +} + +var cmdDownload = &Command{ + UsageLine: "download -server=localhost:9333 -dir=one_directory fid1 [fid2 fid3 ...]", + Short: "download files by file id", + Long: `download files by file id. + + Usually you just need to use curl to lookup the file's volume server, and then download them directly. + This download tool combine the two steps into one. + + What's more, if you use "weed upload -maxMB=..." option to upload a big file divided into chunks, you can + use this tool to download the chunks and merge them automatically. + + `, +} + +func runDownload(cmd *Command, args []string) bool { + for _, fid := range args { + filename, content, e := fetchFileId(*server, fid) + if e != nil { + fmt.Println("Fetch Error:", e) + continue + } + if filename == "" { + filename = fid + } + if strings.HasSuffix(filename, "-list") { + filename = filename[0:len(filename)-len("-list")] + fids := strings.Split(string(content), "\n") + f, err := os.OpenFile(path.Join(*downloadDir, filename), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm) + if err != nil { + fmt.Println("File Creation Error:", e) + continue + } + defer f.Close() + for _, partId := range fids { + var n int + _, part, err := fetchFileId(*server, partId) + if err == nil { + n, err = f.Write(part) + } + if err == nil && n < len(part) { + err = io.ErrShortWrite + } + if err != nil { + fmt.Println("File Write Error:", err) + break + } + } + } else { + ioutil.WriteFile(path.Join(*downloadDir, filename), content, os.ModePerm) + } + } + return true +} + +func fetchFileId(server string, fildId string) (filename string, content []byte, e error) { + fileUrl, lookupError := operation.LookupFileId(server, fildId) + if lookupError != nil { + return "", nil, lookupError + } + filename, content, e = fetchUrl(fileUrl) + return +} + +func fetchUrl(fileUrl string) (filename string, content []byte, e error) { + response, err := http.Get(fileUrl) + if err != nil { + return "", nil, err + } + defer response.Body.Close() + contentDisposition := response.Header["Content-Disposition"] + if len(contentDisposition) > 0 { + glog.V(4).Info("Content-Disposition: ", contentDisposition[0]) + if strings.HasPrefix(contentDisposition[0], "filename=") { + filename = contentDisposition[0][len("filename="):] + } + } else { + glog.V(4).Info("No Content-Disposition!") + } + content, e = ioutil.ReadAll(response.Body) + return +} + +func WriteFile(filename string, data []byte, perm os.FileMode) error { + f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) + if err != nil { + return err + } + n, err := f.Write(data) + f.Close() + if err == nil && n < len(data) { + err = io.ErrShortWrite + } + return err +} diff --git a/go/weed/weed.go b/go/weed/weed.go index 0b1512636..3d4beac88 100644 --- a/go/weed/weed.go +++ b/go/weed/weed.go @@ -22,10 +22,11 @@ var IsDebug *bool var server *string var commands = []*Command{ - cmdCompact, + cmdCompact, cmdFix, cmdMaster, cmdUpload, + cmdDownload, cmdShell, cmdVersion, cmdVolume,