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

Python 如何从发布的base64编码图像创建MongoDB/mongoengine ImageField?,python,mongodb,python-imaging-library,mongoengine,imagefield,Python,Mongodb,Python Imaging Library,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 i

我有一个小型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(位置:53e37ed6844de403e0998182)(image.grid:['images'])

    当我将图像数据的指定更改为:

    img.data.put(PILImage)
    
    我得到错误:#=>验证错误:无效图像:读取

    所以我认为它可能正在寻找一个支持“read”方法的对象。当我将作业更改为以下内容时:

    img.data.put(file_like)
    
    我收到错误:#=>“验证错误:无效图像:无法识别图像文件”

    因此,我能够对数据进行base64编码、json.loads()、POST、json.dumps()、base64解码并创建一个PIL图像,但我无法让MongoDB ImageField将其作为图像接受

    有人能帮忙吗

    有一件事:我发现,如果我简单地将PILImage写入磁盘,然后通过告诉mongoengine

    img.data.put("path/to/image/file")
    

    我可以解决这个问题,但我希望避免文件系统操作,因为应用程序将遇到相当多的流量,我们怀疑IO将是第一个瓶颈。

    如果您仍然需要它,这里是我的解决方案:

    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成本。是的,这会在文件系统上创建一个实际的临时文件。但根据Mongo doc的说法,这是将img保存到和ImageField的唯一方法。temp文件的一个好处是,一旦您退出了语句(通过正常的exit、return、exception或其他方式),文件/目录及其内容将从文件系统中删除。如果要避免I/O开销,可以尝试将映像保存在StringField中的base64中。希望能有所帮助,抱歉这么晚才回复。谢谢回复。我想这基本上意味着,如果不在I/O方面付出一些小的代价,这是不可能的。您的答案是最接近的(tempfile或stringfield)。谢谢做了这件事,很有魅力。现在尝试查询存储的图像。因此,如果有人知道: