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

3 投票
1 回答
3101 浏览
提问于 2025-04-18 16:24

我有一个小的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 (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()

希望对你有帮助

撰写回答