Reputation: 75
I have a small Python/Flask application that should store a picture in MongoDB.
The Model:
class Image(db.EmbeddedDocument):
data = db.ImageField()
Right now, the relevant server code looks like this:
import Image as PIL
import base64
import cStringIO # I'm trying to give PIL something that can handle common file operations without having to write to disk
imageData = jsondata['image']
file_like = cStringIO.StringIO(base64.decodestring(imageData))
PILImage = PIL.open(file_like)
# new mongo object
img = Image(name="imagename")
img.data = PILImage # assignment of image data
img.save()
This gives me the error #=>ValidationError: ValidationError (Location:53e37ed6844de403e0998182) (image.grid_id: ['images'])
When I change the assignment of the image data to this:
img.data.put(PILImage)
I get the error: #=> ValidationError: Invalid image: read
So I thought it perhaps is looking for an object that supports a 'read' method. When I change the assignment to this:
img.data.put(file_like)
I get the error: #=> "ValidationError: Invalid image: cannot identify image file "
So, I'm able to base64-encode, json.loads(), POST, json.dumps(), base64decode, and create a PIL image from the data, but I somehow can't get the MongoDB ImageField to accept it as an image.
Can anyone help?
One thing: I found that if I simply write the PILImage to disk and then store it by telling mongoengine to
img.data.put("path/to/image/file")
I can work around this, but I would like to avoid filesystem operations, as the application will experience a fair amount of traffic and we suspect IO will be the first bottleneck.
Upvotes: 3
Views: 3154
Reputation: 131
If you still need it, here it is my solution:
import tempfile
# this can change depending if you send the JSON by url or not
file_like = base64.b64decode(imageData)
bytes_image = bytearray(file_like)
with tempfile.TemporaryFile() as f:
f.write(bytes_image)
f.flush()
f.seek(0)
img.data.put(f)
img.save()
Hope it helps
Upvotes: 3