Uploading images and making thumbnails with web.py and PIL
I ran into an issue today while trying to implement image uploads. It’s a very basic implementation: taking files from a POST request, copying them to a local folder, and then making thumbnails of them.
I started with the file upload tutorial in the web.py cookbook.
The problem I was getting was that the Python Image library (PIL) was failing to make the thumbnails, with the error ‘image file is truncated’.
Guessing that the upload was not yet complete when the thumbnail was initiated, I googled around for some help and came across the idea of ‘chunking’. This method copies the file upload to the destination folder in chunks as it arrives.
From this tutorial:
while 1:
chunk = sourceFile.file.read( 10000 )
if not chunk:
break
destFile.write( chunk )
destFile.close()
I tried this method in web.py, using web.input(file = {}) to get the file field from the POST form, and then file.value.read(10000) in the code above. This fails because file.value does not have a .read() method – this is a file object method. Using file.file.read(10000) instead seems to work fine.
I’ve ended up with this:
def POST(self, path = ''):
self.path = path
input = web.input(file = {})
action = input['action']
if action == 'upload':
file = input['file']
f = open(config.root + 'static/uploads/' + file.filename, "wb")
while 1:
chunk = file.file.read(10000 )
if not chunk:
break
f.write( chunk )
f.close()
self.thumbnail(path, file.filename)
self.output()
def thumbnail(self, path, filename):
size = 128, 128
outfile = open(config.root + 'static/resized/' + filename, "wb")
im = Image.open(config.root + 'static/uploads/' + filename)
im.thumbnail(size)
im.save(outfile, "JPEG")
[...] the end, I found the reason and the solution on a blog by Joe Lanman (http://www.joelanman.com/archives/10): I was not closing the file before trying to re-size it. Yes, yes, I know, amateur hour, but the [...]