pymongo 从 GridFS 中获取图像

Posted

技术标签:

【中文标题】pymongo 从 GridFS 中获取图像【英文标题】:pymongo Get an Image Back Out of GridFS 【发布时间】:2012-01-30 16:33:30 【问题描述】:

我正在使用 MongoDB 和 pymongo API。我可以将图像文件放入 GridFS - 看起来很简单:

>>> f = open('myimage.jpg', 'r')
>>> fs = gridfs.GridFS(db)
>>> fid = fs.put(f)
>>> fid
ObjectId('4efde2c27c7778121800000a')

看起来它已经奏效了。我还可以使用返回的 _id 查询 GridFS:

>>> fs.exists(fid)
True

但我似乎无法恢复整个文件 - 看起来我得到了一个 chunK?

>>> fs.get(fid).read()
'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x00Z\x00Z\x00\x00\xff\xdb\x00C\x00
\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01
\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x02\x02\x01\x01
\x02\x01\x01\x01\x02\x02\x02\x02\x02\x02\x02\x02\x02\x01\x02\x02\x02\x02\x02\x02
\x02\x02\x02\x02\xff\xdb\x00C\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x02\x0
1\x01\x01\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x0
2\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x0
2\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\xff\xc0\x00\x11\x08\x03\x8d\x0
2X\x03\x01"\x00\x02\x11\x01\x03\x11\x01\xff\xc4\x00\x1f\x00\x00\x01\x05\x01\x01\
x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\
t\n\x0b\xff\xc4\x00\xb5\x10\x00\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04\x00\
x00\x01\x01\x02\x03\x00\x04\x11\x05\x12!1A\x06\x13Qa\x07"q\x142\x81\x91\xa1\x08
#B\xb1\xc1\x15R\xd1\xf0$3br\x82\t\n\x16\x17\x18\x19'
>>> f.tell()
352256L

我对原始文件做了一个 tell(),你可以看到它比我从 GridFS 中得到的要大得多。如果我对从 GridFS 返回的文件执行 tell(),则它位于 274 区域内。(我知道 tell() 只是告诉您文件中的指针位置,但它表明它有多大是在阅读之后。)

我显然在这里遗漏了一些东西!如何将文件从 GridFS 中全部取出?

我在 python 的 v2.7 上运行 v2.0.2 的 mongodb 和 v2.1 的 pymongo。

【问题讨论】:

您可以使用GridOut.length 查看实际存储了多少字节,这可以告诉您是没有取出所有字节还是文件没有完全存储。 @cpburnz - 谢谢 - 是的,我也试过了,返回值 274(与使用 tell() 相同),这让我认为这是我要返回的一个块。 你用的是什么版本的pymongo? 对不起,应该在问题中包含这个 - 我正在使用 v2.1 的 pymongo 并运行 v2.0.2 的 mongod。 您上面的代码应该可以工作。需要注意的一点是,如果您已经对文件进行了read()seek()-ed,那么GridFS 只会从当前文件“光标”位置开始写入数据库。如果您要小心(并且您正在使用可搜索文件),您可以在 fs.put(...) 之前添加 f.seek(0, 0) 以显式搜索到开头。 【参考方案1】:

您可以尝试检查 GridFS 是否实际保存了整个文件,即您没有通过 mongo 控制台写入文件的一部分。这应该列出您的图像以及其他图像以及每个文件的长度。因此,您可以验证 GridFS 是否实际保存了整个文件。

db.fs.files.find().pretty()

如果它没有完全保存您的文件,那么可能是您在将其写入 GridFS 时做了一些乱七八糟的事情(就像 @dcrosta 所说的那样)

*注意:将上述命令中的集合名称替换为“fs”。喜欢:

db.<my_collection_name>.files.find().pretty()

如果您有很多文件,请尝试:

db.<my_collection_name>.files.findOne('_id' : ObjectId("your object id as a hex string"))

【讨论】:

【参考方案2】:

尝试将 'r' 更改为 'rb',如下所示:&gt;&gt;&gt; f = open('myimage.jpg', 'rb')

根据您的平台(win/linux/mac),这可能会导致问题

【讨论】:

【参考方案3】:

获取数据输出数据

outputdata =fs.get(stored).read()

定义文件路径并开启写入模式

outfilename = "path to output file"
output= open(outfilename,"w")

写入数据并关闭文件

output.write(outputdata)
output.close()

【讨论】:

以上是关于pymongo 从 GridFS 中获取图像的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PyMongo 的 GridFS 中打开文件的 GridOut 实例?

Pymongo GridFS 放置类型/属性错误

使用烧瓶中的 send_file() 时文件损坏,pymongo gridfs 中的数据

MongoDB Gridfs NODE 显示图片

使用 GridFs 从 mongoDB 读取和显示图像

如何使用 Sails.JS + GridFS 从 Mongo 检索图像文件?