pymongo Получить изображение обратно из GridFS

Я играю с MongoDB и API pymongo. Я могу поместить файл изображения в GridFS - кажется, прямолинейно:

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

Похоже, это сработало. Я также могу запросить GridFS, используя возвращенный _id:

>>> fs.exists(fid)
True

Но мне кажется, что я не могу вернуть ВЕСЬ файл - похоже, я получаю кусок?

>>> 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. Если я использую tell () для файла, который я получаю из GridFS, он находится в районе 274. (Я понимаю, что tell () просто сообщает вам местоположение указателя в файле, но дает указание на его размер. после прочтения.)

Мне здесь явно чего-то не хватает! Как я могу полностью вернуть файл из GridFS?

Я использую mongodb v2.0.2 и pymongo v2.1 на python v2.7.


person RobertMS    schedule 30.12.2011    source источник
comment
Вы можете использовать GridOut.length, чтобы увидеть, сколько байтов фактически сохранено, что может дать вам представление о том, выводятся ли вы не все байты или файл не был полностью сохранен.   -  person All Workers Are Essential    schedule 30.12.2011
comment
@cpburnz - Спасибо - Да, я тоже пробовал, возвращает значение 274 (так же, как при использовании tell ()), что наводит меня на мысль, что это кусок, который я возвращаю.   -  person RobertMS    schedule 30.12.2011
comment
Какую версию пимонго вы используете?   -  person dcrosta    schedule 30.12.2011
comment
Извините, я должен был включить это в вопрос - я использую v2.1 pymongo и запускаю v2.0.2 mongod.   -  person RobertMS    schedule 30.12.2011
comment
Приведенный выше код должен работать. Следует отметить, что если вы уже read() или seek()-ed в файле, то GridFS начнет запись в базу данных только с текущей позиции курсора файла. Если вы хотите быть осторожными (и вы работаете с файлами, доступными для поиска), вы можете добавить f.seek(0, 0) перед fs.put(...), чтобы явно вернуться к началу.   -  person dcrosta    schedule 30.12.2011
comment
Спасибо - я попробовал, и это не помогло. Пробовал выложить файл через приложение mongofiles - сработало. Затем я мог бы использовать pymongo, чтобы увидеть, что файл существует (работал), и я мог бы использовать GridFS.get_last_version (filename), чтобы получить экземпляр GridOut. Используя это, я вижу, что размер файла составляет 355846, что я и ожидал увидеть. Использование mongofiles -get позволило мне вернуть файл из GridFS, и он был идентичен оригиналу. Итак, я должен делать что-то неправильно, читая файл в GridFS, используя pymongo и файловый объект. Я не опытный разработчик Python, видите ли вы что-нибудь очевидное? Спасибо   -  person RobertMS    schedule 03.01.2012
comment
несколько вещей, которые нужно проверить - 1) если вы работаете в Windows, откройте файл в режиме 'rb', а не только 'r'. 2) убедитесь, что файл, который вы открываете, полностью записан, прежде чем вставлять его в mongo. 3) убедитесь, что f находится в начале файла перед вызовом put ()   -  person Chris AtLee    schedule 06.05.2012


Ответы (3)


Вы можете попробовать проверить, действительно ли GridFS хранит весь файл, т.е. вы не записали часть файла через консоль mongo. В нем должно быть указано ваше изображение вместе с другими, а также длина каждого файла. Таким образом, вы можете проверить, действительно ли GridFS хранит ваш файл целиком или нет.

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

Если он не удерживает ваш файл полностью, вероятно, вы сделали что-то беспорядочное при записи его в GridFS (например, what сказал @ dcrosta)

* Примечание: замените название вашей коллекции в приведенной выше команде на «fs». Нравится:

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

Если у вас много файлов, попробуйте:

db.<my_collection_name>.files.findOne({'_id' : ObjectId("your object id as a hex string")})
person Ishan Khare    schedule 10.12.2014

Попробуйте изменить 'r' на 'rb' следующим образом: >>> f = open('myimage.jpg', 'rb')

В зависимости от вашей платформы (win / linux / mac) это может вызвать проблемы.

person Robin Nemeth    schedule 22.07.2015

Получить данные в outputdata

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

Определите путь к файлу и откройте режим записи

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

Записать данные и закрыть файл

output.write(outputdata)
output.close()
person burakozgul    schedule 02.08.2016