1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>22. How to stream uploaded files directly to disk</title>
<META NAME="description" CONTENT="22. How to stream uploaded files directly to disk">
<META NAME="keywords" CONTENT="howto">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="STYLESHEET" href="howto.css" type='text/css'>
<link rel="first" href="howto.html">
<link rel="contents" href="contents.html" title="Contents">
<LINK REL="next" HREF="node24.html">
<LINK REL="previous" HREF="node22.html">
<LINK REL="up" HREF="howto.html">
<LINK REL="next" HREF="node24.html">
<meta name='aesop' content='information'>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node22.html"><img src="../icons/previous.gif"
border="0" height="32"
alt="Previous Page" width="32"></A></td>
<td><A HREF="howto.html"><img src="../icons/up.gif"
border="0" height="32"
alt="Up One Level" width="32"></A></td>
<td><A HREF="node24.html"><img src="../icons/next.gif"
border="0" height="32"
alt="Next Page" width="32"></A></td>
<td align="center" width="100%">CherryPy HowTo</td>
<td><A HREF="node1.html"><img src="../icons/contents.gif"
border="0" height="32"
alt="Contents" width="32"></A></td>
<td><img src="../icons/blank.gif"
border="0" height="32"
alt="" width="32"></td>
<td><img src="../icons/blank.gif"
border="0" height="32"
alt="" width="32"></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node22.html">21. Sample deployment configuration</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="howto.html">CherryPy HowTo</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node24.html">About this document ...</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H1><A NAME="SECTION0023000000000000000000">
22. How to stream uploaded files directly to disk</A>
</H1>
<P>
By default, CherryPy handles in the same way all data posted to the server through a form. In all cases, CherryPy
converts that data to a string or a list of strings. This data can be a short string or a big file that's being uploaded.
<P>
In most cases, this is very convenient and it works very well. However, if your application requires users to upload very
big files, then converting them to a string and having this string in memory can be a problem ...
<P>
In that case, you may want to write these files directly to a file instead of having them in memory.
<P>
Here is how this can be done:
<UL>
<LI>Use the <var>initRequestBeforeParse</var> special function to tell CherryPy not to parse the POST data itself (by setting <var>request.parsePostData</var> to 0).
</LI>
<LI>Use the <var>FieldStorage</var> class of the <var>cgi</var> module to parse the POST data (by reading <var>request.rfile</var>) and stream the uploaded file to disk.
</LI>
</UL>
<P>
Here is an example code that does this:
<P>
<div class="verbatim"><pre>
import cgi
def initRequestBeforeParse():
if request.path == 'postFile':
request.parsePostData = 0
CherryClass Root:
mask:
def index(self):
<html><body>
<form method=post action=postFile enctype="multipart/form-data">
Upload a file: <input type=file name=myFile><br>
<input type=submit>
</form>
</body></html>
view:
def postFile(self):
# Use cgi.FieldStorage to parse the POST data
dataDict = cgi.FieldStorage(fp=request.rfile, headers=request.headerMap, environ={'REQUEST_METHOD':'POST'}, keep_blank_values=1)
value = dataDict['myFile']
# Value has 2 attributes:
# - filename contains the name of the uploaded file
# - file is an input stream opened for reading
f = open('/tmp/myFile', 'wb')
while 1:
data = value.file.read(1024 * 8) # Read blocks of 8KB at a time
if not data: break
f.write(data)
f.close()
return "<html><body>The file has been saved in /tmp/myFile</body></html>"
</pre></div>
<P>
Note that the file is not streamed directly from the browser to <span class="file">/tmp/myFile</span>. Instead, it is saved in a <var>tempfile</var>
by the <var>cgi</var> module and then streamed from this <var>tempfile</var> to <span class="file">/tmp/myFile</span>.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node22.html"><img src="../icons/previous.gif"
border="0" height="32"
alt="Previous Page" width="32"></A></td>
<td><A HREF="howto.html"><img src="../icons/up.gif"
border="0" height="32"
alt="Up One Level" width="32"></A></td>
<td><A HREF="node24.html"><img src="../icons/next.gif"
border="0" height="32"
alt="Next Page" width="32"></A></td>
<td align="center" width="100%">CherryPy HowTo</td>
<td><A HREF="node1.html"><img src="../icons/contents.gif"
border="0" height="32"
alt="Contents" width="32"></A></td>
<td><img src="../icons/blank.gif"
border="0" height="32"
alt="" width="32"></td>
<td><img src="../icons/blank.gif"
border="0" height="32"
alt="" width="32"></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node22.html">21. Sample deployment configuration</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="howto.html">CherryPy HowTo</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node24.html">About this document ...</A>
<hr>
<span class="release-info">Release 0.10, documentation updated on 19 March 2004.</span>
</DIV>
<!--End of Navigation Panel-->
<ADDRESS>
See <i><a href="about.html">About this document...</a></i> for information on suggesting changes.
</ADDRESS>
</BODY>
</HTML>
|