user3367157
user3367157

Reputation: 11

Looking for wsgi way of processing forms like mod_python Publisher

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

Answers (1)

JasonMArcher
JasonMArcher

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

Related Questions