~chris-atlee/blobs/main

« back to all changes in this revision

Viewing changes to blobc.py

  • Committer: Chris AtLee
  • Date: 2008-02-19 16:55:03 UTC
  • Revision ID: chris@atlee.ca-20080219165503-0i5wcwtx04zphrhd
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python2.5
 
2
"""
 
3
Blob File Server client
 
4
"""
 
5
import hashlib, os, email
 
6
import simplejson
 
7
from blobs.client.httpclient import HTTPClient, FileProxy
 
8
 
 
9
class BlobClient(object):
 
10
    def __init__(self, url):
 
11
        """
 
12
        Creates a new client object
 
13
        You must pass in the url to the Blob server
 
14
        """
 
15
        self.client = HTTPClient(url)
 
16
 
 
17
    def getFile(self, hash, output):
 
18
        url = "/files/%s" % hash
 
19
 
 
20
        res = self.client.get(url)
 
21
 
 
22
        if res.status != 200:
 
23
            raise ValueError("File not found")
 
24
 
 
25
        if hasattr(output, "write"):
 
26
            fp = output
 
27
        else:
 
28
            if os.path.isdir(output):
 
29
                contentDisp = res.getheader("content-disposition", None)
 
30
                msg = email.message_from_string(str(res.msg))
 
31
                filename = msg.get_filename()
 
32
                fp = open(filename, "w")
 
33
            else:
 
34
                fp = open(output, "w")
 
35
 
 
36
        while True:
 
37
            data = res.read(4096)
 
38
            if not data:
 
39
                break
 
40
            fp.write(data)
 
41
 
 
42
    def putFile(self, filename, formparam="file", size = None,
 
43
                inputFileObj = None):
 
44
 
 
45
        if inputFileObj is None:
 
46
            inputFileObj = open(filename)
 
47
 
 
48
        if size is None:
 
49
            size = os.path.getsize(filename)
 
50
 
 
51
        res = self.client.post("/files",
 
52
                {formparam: FileProxy(filename = filename,
 
53
                    file_obj = inputFileObj, size = size),
 
54
                 'filename': filename})
 
55
 
 
56
        return res.status, res.reason
 
57
 
 
58
    def listFiles(self):
 
59
        res = self.client.get("/files.json")
 
60
 
 
61
        return simplejson.load(res)
 
62
 
 
63
if __name__ == "__main__":
 
64
    from optparse import OptionParser
 
65
    import os, sys
 
66
 
 
67
    parser = OptionParser()
 
68
    parser.set_defaults(action=None,
 
69
            server=os.environ.get("BLOB_SERVER"),
 
70
            output=".")
 
71
 
 
72
    parser.add_option("-s", "--server", dest="server",
 
73
            help="Specify the server to connect to.  Alternatively set the BLOB_SERVER environment variable")
 
74
    parser.add_option("-l", "--list", dest="action", action="store_const",
 
75
            const="list", help="Print file listing")
 
76
    parser.add_option("-u", "--upload", dest="action", action="store_const",
 
77
            const="upload",
 
78
            help="Upload the specified file(s) to the server")
 
79
    parser.add_option("-d", "--download", dest="action", action="store_const",
 
80
            const="download",
 
81
            help="Download the specified list of files given as a list of hashes")
 
82
    parser.add_option("-o", "--output", dest="output",
 
83
            help="""Where to save the downloaded file(s).  If multiple files
 
84
are to be downloaded, then this must be a directory.
 
85
 
 
86
Otherwise, if a single file is to be downloaded, this can be the name of a file
 
87
to write to.  It can also be the directory to save the file into, in which case the original filename will be preserved.  It can also be '-' then output will be written to stdout""")
 
88
 
 
89
    options, args = parser.parse_args()
 
90
 
 
91
    if not options.server:
 
92
        parser.error("Need to specify a server")
 
93
 
 
94
    c = BlobClient(options.server)
 
95
 
 
96
    if options.action == "list":
 
97
        for h, size, filename in c.listFiles():
 
98
            print h, filename
 
99
 
 
100
    elif options.action == "upload":
 
101
        for fn in args:
 
102
            print c.putFile(fn)
 
103
 
 
104
    elif options.action == "download":
 
105
        if len(args) == 1:
 
106
            if options.output == "-":
 
107
                c.getFile(args[0], sys.stdout)
 
108
            elif os.path.isdir(options.output):
 
109
                c.getFile(args[0], options.output)
 
110
            else:
 
111
                c.getFile(args[0], open(options.output, "w"))
 
112
        else:
 
113
            if options.output == "-":
 
114
                parser.error("You cannot output to stdout when multiple files are downloaded")
 
115
            elif not os.path.isdir(options.output):
 
116
                parser.error("You must output to a directory when multiple files are downloaded")
 
117
 
 
118
            for h in args:
 
119
                c.getFile(h, options.output)