Search code examples
google-app-enginewebapp2

For <input type="file" ...> self.request.POST[name] is just a string


Using the GAE "helloworld" example app as a base, but changing "helloworld.py" to:

import webapp2

class MainPage(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/html'
        self.response.write(
            """
            <form method="post">
                UPLOAD: <input type="file" name="file_param"/>
                <br/>
                <input type="submit" name="submit_param" value="Submit">
            </form>
            """
        )

    def post(self):
        field_storage = self.request.POST["file_param"]
        try:
            mimetype = field_storage.type
            self.response.write("Mimetype: {}".format(mimetype))
        except:
            self.response.write("No FieldStorage object, field_storage={}".format(field_storage))    

app = webapp2.WSGIApplication([('/', MainPage)], debug=True)

Running this in Google Chrome on Mac OSX:

  1. Click "Choose File"
  2. Choose a file to upload
  3. Click "Submit"

The page that comes back says:

No FieldStorage object, field_storage=<the name of the file I uploaded>

According to http://webapp-improved.appspot.com/guide/request.html#files and examples in various posts, self.request.POST[name] should be a cgi.FieldStorage object. But as this example shows, self.request.POST[name] is a string containing the filename of the uploaded file. If it were a cgi.FieldStorage object, I would expect the program to display the mimetype of the uploaded file.

I need the cgi.FieldStorage object so I can get the mimetype and of course the value, that is, the content of the file. What am I doing wrong?

By the way, switching from webapp2 to webapp (using from google.appengine.ext import webapp) made no difference. Also, running it in Safari or Firefox, it behaved the same as in Chrome.


Solution

  • The form's enctype must be multipart/form-data. Please add it as follows (method attribute is case-insensitive):

    <form method="POST" enctype="multipart/form-data">
    

    Also, please consider using blobstore upload, because it doesn't have size limit, you can also use Google Cloud Storage as a backend, which will give you more flexibility on ACL and sharing capability.