~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to www/apps/download/__init__.py

  • Committer: mattgiuca
  • Date: 2008-01-17 06:54:07 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:243
Added common/zip.py. Creates a zip file from paths in the student directory.
download: Rewrote download app to decide whether to zip up files, and handle
    multiple file requests, and then call common.zip.make_zip.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 
18
18
# App: download
19
19
# Author: Matt Giuca
20
 
# Date: 17/12/2007
 
20
# Date: 17/1/2008
21
21
 
22
22
# Serves content to the user (acting as a web server for students files).
23
23
# Unlike "serve", all content is served as a static file, and with the
24
24
# application/octet-stream mime type.
25
25
# Also can serve directories or multiple files, automatically zipping them up.
26
26
 
27
 
from common import (util, studpath)
 
27
from common import (util, studpath, zip)
28
28
import conf
29
29
 
30
30
import functools
31
31
import os
32
32
import mimetypes
33
 
 
34
 
# TODO: Make it work on multiple files, zipping them up.
35
 
# TODO: Make it work on directories, zipping them up.
 
33
import StringIO
36
34
 
37
35
# Serve all files as application/octet-stream so the browser presents them as
38
36
# a download.
39
37
default_mimetype = "application/octet-stream"
 
38
zip_mimetype = "application/zip"
40
39
 
41
40
def handle(req):
42
41
    """Handler for the Download application which serves files for
43
42
    download."""
 
43
    zipmode = False
 
44
    zipbasepath = None
 
45
    zipfilename = None
 
46
    path = None
44
47
 
45
48
    req.write_html_head_foot = False
46
49
 
47
 
    # Get the username of the student whose work we are browsing, and the path
48
 
    # on the local machine where the file is stored.
49
 
    (user, path) = studpath.url_to_local(req.path)
50
 
 
51
 
    if user is None:
52
 
        # TODO: Nicer 404 message?
53
 
        req.throw_error(req.HTTP_NOT_FOUND)
54
 
 
55
 
    if not os.access(path, os.R_OK):
56
 
        req.throw_error(req.HTTP_NOT_FOUND)
57
 
    req.content_type = default_mimetype
58
 
    req.sendfile(path)
59
 
 
 
50
    # If any "path=" variables have been supplied, bring these into a list and
 
51
    # make a zip file instead.
 
52
    fields = req.get_fieldstorage()
 
53
    paths = fields.getlist("path")
 
54
    if len(paths) > 0:
 
55
        zipmode = True
 
56
        zipbasepath = req.path
 
57
        zipfilename = os.path.basename(zipbasepath)
 
58
        for i in range(0, len(paths)):
 
59
            paths[i] = paths[i].value
 
60
    else:
 
61
        # Otherwise, just serve directly (unless it's a directory)
 
62
        (_, path) = studpath.url_to_local(req.path)
 
63
        if path is None:
 
64
            # TODO: Nicer 404 message?
 
65
            req.throw_error(req.HTTP_NOT_FOUND)
 
66
        elif not os.access(path, os.R_OK):
 
67
            req.throw_error(req.HTTP_NOT_FOUND)
 
68
        # If it's a directory, serve as a zip file
 
69
        if os.path.isdir(path):
 
70
            zipmode = True
 
71
            # Zip it from the perspective of its own parent.
 
72
            # That way it will be a directory in the top level of the zip
 
73
            # file.
 
74
            path = req.path
 
75
            if path[-1] == os.sep: path = path[:-1]
 
76
            splitpath = path.rsplit(os.sep, 1)
 
77
            if len(splitpath) == 1:
 
78
                zipbasepath = ''
 
79
                paths = [path]
 
80
            else:
 
81
                zipbasepath = splitpath[0]
 
82
                paths = [splitpath[1]]
 
83
            zipfilename = paths[0]
 
84
 
 
85
    if zipmode:
 
86
        req.content_type = zip_mimetype
 
87
        # zipfilename is some filename. Strip trailing slash or extension,
 
88
        # and add ".zip".
 
89
        if zipfilename == '':
 
90
            zipfilename = "files"
 
91
        elif zipfilename[-1] == '/':
 
92
            zipfilename = zipfilename[:-1]
 
93
        elif '.' in zipfilename:
 
94
            zipfilename = zipfilename[:zipfilename.rindex('.')]
 
95
        zipfilename += ".zip"
 
96
        req.headers_out["Content-Disposition"] = ("attachment; filename=" +
 
97
            zipfilename)
 
98
        zipfile = StringIO.StringIO()
 
99
        zip.make_zip(zipbasepath, paths, zipfile,req)
 
100
        req.write(zipfile.getvalue())
 
101
    else:
 
102
        req.content_type = default_mimetype
 
103
        req.sendfile(path)