I am using Flask to open an image from a URL.
file = cStringIO.StringIO(urllib.urlopen(URL).read())
img = Image.open(file)
I then want to take the image and save it to my site. When I do this, I get
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/Library/Python/2.7/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/Library/Python/2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/Library/Python/2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/User/Desktop/Flask/fl.py", line 37, in index
img.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
File "/Library/Python/2.7/site-packages/PIL/Image.py", line 1648, in save
raise KeyError(ext) # unknown extension
KeyError: ''
Here is the code to save:
filename = secure_filename(img.filename)
img.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
print url_for('uploaded_file', filename=filename)
@app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
Why is this happening? How can I fix this?
When saving in image from an object without a filename, like a StringIO
object, you need to tell PIL what type of image it is:
img.save(os.path.join(app.config['UPLOAD_FOLDER'], filename), format='PNG')
Here I stated that the format is a PNG, but you'll need to introspect the Content-Type
header from the response and see what type is from that. Map the content type to the appropriate PIL format, based on the header.
You'll also need to come up with a better filename; img.filename
is an empty string as you never gave img.open()
a filename. Use the last component of URL
instead for example; presumably that'll have a filename:
formats = {
'image/jpeg': 'JPEG',
'image/png': 'PNG',
'image/gif': 'GIF'
}
response = urllib.urlopen(URL)
image_type = response.info().get('Content-Type')
try:
format = formats[image_type]
except KeyError:
raise ValueError('Not a supported image format')
file = cStringIO.StringIO(response.read())
img = Image.open(file)
# ...
filename = secure_filename(URL.rpartition('/')[-1])
img.save(os.path.join(app.config['UPLOAD_FOLDER'], filename), format=format)