Reputation: 11
In mod_python Publisher, I could write a file loader, (uploader.py in this example) using code like this:
def index():
html = '''
<html>
<body>
<form id="fileUpload" action="uploader.py/upload" enctype="multipart/form-data" method="post">
<input type="file" id="file" name="file_name"/>
<input type="submit" value="Upload"/>
</form>
</body>
</html>
'''
return html
def upload(req, file_name):
fd = open("/mydir/myfile", "w")
for line in file_name.file.readlines():
fd.write(line)
fd.close()
This example, excludes any error checking but illustrates what I could do with mod_python and Publisher. The key things are that Publisher was able to call my function, upload, in the file uploader.py and pass it an argument, file_name with the attribute file with the file that was selected in the form.
What I want to do is to do the same thing in mod_wsgi. I'm looking for a way to call a function like this from a form and invoke my function in a similar fashion. I've looked at webob but cannot figure out how to do the same thing with this package. I would appreciate any help in coding a similar solution without having to use mod_python and Publisher.
Upvotes: 0
Views: 427
Reputation: 14991
Answer migrated from question text.
After some digging, I figured out a solution to this problem. This is the solution I came up with. I implemented this with two files: uploader1.py and uploader2.py. This is code for uploader1.py:
def application(environ, start_response):
from webob import Response
html = '''
<html>
<body>
<h1>Upload</h1>
<form id="fileUpload" action="uploader2.py" enctype="multipart/form-data" method="post">
<input type="file" name="filename"/>
<input type="submit" value="Upload"/>
</form>
</body>
</html>
'''
response = Response(body = html,
content_type = "text/html",
charset = "utf8",
status = "200 OK")
return response(environ, start_response)
And this is the code for uploader2.py:
import os
import cgi
def application(environ, start_response):
from webob import Response
form = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ, keep_blank_values=True)
try:
fileitem = form['filename']
except KeyError:
fileitem = None
if fileitem is not None and fileitem.filename and fileitem.file:
# remove any relative paths to prevent directory traversal attacks
fn = os.path.basename(fileitem.filename)
# directory to upload to
fn = "/tmp/"+fn
with open(fn, 'w') as f:
# this upload is for text files
lines = fileitem.file.readlines()
for line in lines:
f.write(line)
f.close()
message = "Uploaded file: %s" % fn
else:
message = "Error: no file selected for upload"
html = '''
<html>
<body>
<p>%s
</body>
</html>
''' % message
response = Response(body = html,
content_type = "text/html",
charset = "utf8",
status = "200 OK")
return response(environ, start_response)
The only drawbacks to this implementation over the mod_python one is that I couldn't figure out a way to implement this solution in a single file. mod_python allowed me to call a function within a module and I can't figure out a way to do this with mod_wsgi. Also, during debugging it would have been nice to be able to log output to the same custom error_log file I had set up for mod_wsgi and I couldn't find a way of doing this, so had to log to the main Apache log file by using print statements. If someone has a way of doing this, I would be pleased to know a solution.
Upvotes: 1