如何从POST的base64编码图像创建MongoDB/mongoengine的ImageField?
我有一个小的Python/Flask应用程序,想把一张图片存储到MongoDB里。
- 客户端通过HTTP POST请求发送一个包含JSON格式的数据,其中有一个字段是经过base64编码的图片。
- 服务器需要把这张图片存储到MongoDB的ImageField里。我现在使用的是mongoengine。
这是模型:
class Image(db.EmbeddedDocument):
data = db.ImageField()
目前,相关的服务器代码是这样的:
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()
这段代码让我遇到了一个错误:#=>ValidationError: ValidationError (Location:53e37ed6844de403e0998182) (image.grid_id: ['images'])
当我把图片数据的赋值改成这样的时候:
img.data.put(PILImage)
我又遇到了一个错误:#=> ValidationError: Invalid image: read
所以我在想,可能是它在找一个支持'read'方法的对象。当我把赋值改成这样:
img.data.put(file_like)
我又得到了一个错误:#=> "ValidationError: Invalid image: cannot identify image file "
我可以进行base64编码,使用json.loads(),发送POST请求,使用json.dumps(),进行base64解码,并从数据中创建一个PIL图像,但我就是无法让MongoDB的ImageField接受它作为一张图片。
有没有人能帮帮我?
有一点:我发现如果我直接把PIL图像写入磁盘,然后告诉mongoengine去存储它:
img.data.put("path/to/image/file")
我可以绕过这个问题,但我想避免文件系统操作,因为这个应用会有相当多的流量,我们怀疑IO会是第一个瓶颈。
1 个回答
3
如果你还需要的话,这里是我的解决方案:
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()
希望对你有帮助