| 1 |
""" |
|---|
| 2 |
|
|---|
| 3 |
Tutorial: File upload and download |
|---|
| 4 |
|
|---|
| 5 |
Uploads |
|---|
| 6 |
------- |
|---|
| 7 |
|
|---|
| 8 |
When a client uploads a file to a CherryPy application, it's placed |
|---|
| 9 |
on disk immediately. CherryPy will pass it to your exposed method |
|---|
| 10 |
as an argument (see "myFile" below); that arg will have a "file" |
|---|
| 11 |
attribute, which is a handle to the temporary uploaded file. |
|---|
| 12 |
If you wish to permanently save the file, you need to read() |
|---|
| 13 |
from myFile.file and write() somewhere else. |
|---|
| 14 |
|
|---|
| 15 |
Note the use of 'enctype="multipart/form-data"' and 'input type="file"' |
|---|
| 16 |
in the HTML which the client uses to upload the file. |
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
Downloads |
|---|
| 20 |
--------- |
|---|
| 21 |
|
|---|
| 22 |
If you wish to send a file to the client, you have two options: |
|---|
| 23 |
First, you can simply return a file-like object from your page handler. |
|---|
| 24 |
CherryPy will read the file and serve it as the content (HTTP body) |
|---|
| 25 |
of the response. However, that doesn't tell the client that |
|---|
| 26 |
the response is a file to be saved, rather than displayed. |
|---|
| 27 |
Use cherrypy.lib.static.serve_file for that; it takes four |
|---|
| 28 |
arguments: |
|---|
| 29 |
|
|---|
| 30 |
serve_file(path, content_type=None, disposition=None, name=None) |
|---|
| 31 |
|
|---|
| 32 |
Set "name" to the filename that you expect clients to use when they save |
|---|
| 33 |
your file. Note that the "name" argument is ignored if you don't also |
|---|
| 34 |
provide a "disposition" (usually "attachement"). You can manually set |
|---|
| 35 |
"content_type", but be aware that if you also use the encoding tool, it |
|---|
| 36 |
may choke if the file extension is not recognized as belonging to a known |
|---|
| 37 |
Content-Type. Setting the content_type to "application/x-download" works |
|---|
| 38 |
in most cases, and should prompt the user with an Open/Save dialog in |
|---|
| 39 |
popular browsers. |
|---|
| 40 |
|
|---|
| 41 |
""" |
|---|
| 42 |
|
|---|
| 43 |
import os |
|---|
| 44 |
localDir = os.path.dirname(__file__) |
|---|
| 45 |
absDir = os.path.join(os.getcwd(), localDir) |
|---|
| 46 |
|
|---|
| 47 |
import cherrypy |
|---|
| 48 |
from cherrypy.lib import static |
|---|
| 49 |
|
|---|
| 50 |
|
|---|
| 51 |
class FileDemo(object): |
|---|
| 52 |
|
|---|
| 53 |
def index(self): |
|---|
| 54 |
return """ |
|---|
| 55 |
<html><body> |
|---|
| 56 |
<form action="upload" method="post" enctype="multipart/form-data"> |
|---|
| 57 |
filename: <input type="file" name="myFile" /><br /> |
|---|
| 58 |
<input type="submit" /> |
|---|
| 59 |
</form> |
|---|
| 60 |
</body></html> |
|---|
| 61 |
""" |
|---|
| 62 |
index.exposed = True |
|---|
| 63 |
|
|---|
| 64 |
def upload(self, myFile): |
|---|
| 65 |
out = """<html> |
|---|
| 66 |
<body> |
|---|
| 67 |
myFile length: %s<br /> |
|---|
| 68 |
myFile filename: %s<br /> |
|---|
| 69 |
myFile mime-type: %s |
|---|
| 70 |
</body> |
|---|
| 71 |
</html>""" |
|---|
| 72 |
|
|---|
| 73 |
|
|---|
| 74 |
|
|---|
| 75 |
|
|---|
| 76 |
|
|---|
| 77 |
size = 0 |
|---|
| 78 |
while True: |
|---|
| 79 |
data = myFile.file.read(8192) |
|---|
| 80 |
if not data: |
|---|
| 81 |
break |
|---|
| 82 |
size += len(data) |
|---|
| 83 |
|
|---|
| 84 |
return out % (size, myFile.filename, myFile.type) |
|---|
| 85 |
upload.exposed = True |
|---|
| 86 |
|
|---|
| 87 |
def download(self): |
|---|
| 88 |
path = os.path.join(absDir, "pdf_file.pdf") |
|---|
| 89 |
return static.serve_file(path, "application/x-download", |
|---|
| 90 |
"attachment", os.path.basename(path)) |
|---|
| 91 |
download.exposed = True |
|---|
| 92 |
|
|---|
| 93 |
|
|---|
| 94 |
cherrypy.tree.mount(FileDemo()) |
|---|
| 95 |
|
|---|
| 96 |
if __name__ == '__main__': |
|---|
| 97 |
import os.path |
|---|
| 98 |
thisdir = os.path.dirname(__file__) |
|---|
| 99 |
cherrypy.quickstart(config=os.path.join(thisdir, 'tutorial.conf')) |
|---|