1

EDIT: Added the solution to my code, as suggested by Martijn Pieters.

I'm writing a web application that should have an image upload feature. Actually it is uploading directly to imgur.com through their api. So far I can upload an image to imgur through the terminal by running my python script. But I want the user to be able to select an image through an html form. All I actually need (I think) is the path for the file, then I have a script that converts the image to base64. As I write this I realize that the script might only work when it's run locally, and not from a browser. I have been googling for two days. I get a lot of results about cgi.FieldStorage() but can't seem to get that to work as I get a KeyError.

This is the file input part of my form:

<div class="container">
    <form role="form" class="form-horizontal form-inline" method="post" enctype="multipart/form-data">
        <div class="col-md-12">
            <div class="form-group">
                <label for="image" class="control-label">Product image</label>
                <input type="file" id="image" name="imageurl" value=""/>
            </div>
        </div>

And then I need to be able to handle the input in my python script:

class MainPage(BlogHandler):
    def get(self):
        self.render("front.html")

    def post(self):
        image = self.request.POST.get("imageurl")
        logging.info(getUrl(image))

This is the code for sending the image to the imgur api:

def getUrl(image):
    API_URL = "https://api.imgur.com/3/upload.json"

    image_read = image.file.read()
    b64 = base64.b64encode(image_read)

    data = {
        'image': b64,
        'type': base64,
        'title': 'testupload'
    }

    response = requests.post(API_URL, data, headers={'Authorization': 'Client-ID my-cient-id'})
    url = response.json()['data']['link']
    return url

I developing in Google App Engine and using Jinja2 as the templating engine.

I'm a beginner programmer so I hope to get some pointers on my problem. I feel like I'm stuck on searching for the answer. I've read that the browser does not know anything about the file system of the computer for security reasons, but websites exist where you can choose a file from your computer to upload, so I figure it must be possible to achieve. :)

EDIT: Added the solution to my code, as suggested by Martijn Pieters.

Bach
  • 5,661
  • 6
  • 25
  • 57
Gobias
  • 33
  • 1
  • 5

1 Answers1

0

Uploading an image requires that you change the form encoding to multipart/form-data:

<form encoding="multipart/form-data" role="form" class="form-horizontal form-inline" method="post">

See application/x-www-form-urlencoded or multipart/form-data?

Because this is a POST request, you'll find the fields in request.POST:

def post(self):
    imageurl = self.request.POST.get("imageurl")
    logging.info(imageurl)

although request.get() will search both query parameters and POST form data.

A form upload is returned as a cgi.FieldStorage() object; this has a file attribute, which gives you a file-like interface. You could just read the data into memory:

image = self.request.POST.get("imageurl")
image_read = image.file.read()
b64 = base64.b64encode(image_read)
Community
  • 1
  • 1
Martijn Pieters
  • 889,049
  • 245
  • 3,507
  • 2,997
  • So now I get a FieldStorage item, but I'm unsure on how to feed this into my getUrl() function shown above. – Gobias Jun 19 '14 at 17:46