Chris Lu
11 years ago
2 changed files with 122 additions and 1 deletions
@ -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 |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue