如何从POST的base64编码图像创建MongoDB/mongoengine ImageField?

3

我有一个小的Python/Flask应用程序,应该将图片存储在MongoDB中。

  1. 客户端提交HTTP POST(JSON),其中一个字段是base64编码的图像。
  2. 服务器应该将这个图像存储在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 (位置: 53e37ed6844de403e0998182) (image.grid_id: ['images'])

当我将图像数据的赋值更改为以下内容时:

img.data.put(PILImage)

我会尽力为您翻译。这是需要翻译的内容:

我得到了一个错误:# => 验证错误:无效图像:read

因此,我认为它可能正在寻找支持“read”方法的对象。当我将赋值更改为以下内容时:

img.data.put(file_like)

我遇到了错误:#=>“ValidationError:Invalid image:cannot identify image file”。我可以将数据进行base64编码,json.loads(),POST,json.dumps(), base64decode,并创建一个PIL图像。但是,MongoDB的ImageField无法将其识别为图像。有人能帮忙吗?需要注意的一件事是:如果我只是将PILImage直接写入磁盘,然后通过告知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()

希望能对你有所帮助。

这会在文件系统上创建一个实际的(临时)文件,对吗?我想避免这种情况,因为会有数百个这样的事务几乎同时发生,从而导致I/O成本过高。 - gmonk
是的,这会在文件系统上创建一个实际的临时文件。但根据Mongo文档,这是将图像保存到ImageField的唯一方法。关于临时文件的好处是,一旦您退出语句(通过正常退出、返回、异常或任何其他方式),文件/目录及其内容将从文件系统中删除。如果您想避免I/O成本,可以尝试在StringField中以base64格式保存图像。希望能有所帮助,很抱歉回复晚了。 - andresarenasv
感谢您的回复。我想这基本上意味着在I/O方面不付出一些小代价是不可能的。您的答案已经尽可能地接近了(使用tempfile或stringfield)。谢谢! - gmonk
做到了,非常顺利。现在正在尝试查询存储的图像。如果有人知道,请在此处提供:https://stackoverflow.com/questions/44889557/flask-mongoengine-paginated-documents-with-image-field - David Crook

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接