6

I have a png file which should be convert to jpg and save to gridfs , I use python's PIL lib to load the file and do the converting job, the problem is I want to store the converted image to a MongoDB Gridfs, in the saving procedure, I can't just use the im.save() method. so I use a StringIO to hold the temp file but it don't work.

here is the code snippet:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from PIL import Image
from pymongo import MongoClient
import gridfs
from StringIO import StringIO


im = Image.open("test.png").convert("RGB")

#this is what I tried, define a 
#fake_file with StringIO that stored the image temporarily.
fake_file = StringIO()
im.save(fake_file,"jpeg")

fs = gridfs.GridFS(MongoClient("localhost").stroage)

with fs.new_file(filename="test.png") as fp:
    # this will not work
    fp.write(fake_file.read())


# vim:ai:et:sts=4:sw=4:

I am very verdant in python's IO mechanism, How to make this work?

armnotstrong
  • 8,605
  • 16
  • 65
  • 130

1 Answers1

8

Use the getvalue method instead of read:

with fs.new_file(filename="test.png") as fp:
    fp.write(fake_file.getvalue())

Alternatively, you could use read if you first seek(0) to read from the beginning of the StringIO.

with fs.new_file(filename="test.png") as fp:
    fake_file.seek(0)
    fp.write(fake_file.read())
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • thanks, That works, but why I should `seek(0)` first to get `read()` work? it's confusing and weird. – armnotstrong Jan 23 '15 at 04:21
  • And I don't find any specification about the `StringIO.read()` method in the [official document](https://docs.python.org/2/library/stringio.html#module-StringIO) where can I learn more about the behavior of this `read()` method of `StringIO` ? – armnotstrong Jan 23 '15 at 04:26
  • `StringIO` is explicitly designed to be like a file. You have just finished writing to the "file," therefore the file pointer is at the end of the "file". So reading doesn't get anything, because you're at the end of the "file." That's why you have to `seek(0)` to read it. Because it's like a file. It works just like you'd expect it to work. – kindall Jan 23 '15 at 05:54
  • @armnotstrong: The second sentence in [the docs for StringIO](https://docs.python.org/2/library/stringio.html#module-StringIO) links to [the docs for file objects](https://docs.python.org/2/library/stdtypes.html#file-objects). There you'll find all the methods `StringIO` shares with file objects. – unutbu Jan 23 '15 at 12:15
  • 1
    @unutbu +1 for the ```.seek(0)``` hint. For me it was required to do ```Image.open(fake_file)``` with PIL – coreyt Jul 30 '15 at 02:44