2

User upload a image file by the Form, I don't want to save original uploaded image file to disk, and resize image by Pillow opening image from disk.

I want to resize this image file in memory first, then save the resized image file to disk. so I import StringIO as buffer, but it does't work with Pillow.

Here is the code:

Python3.4, Flask==0.10.1, Pillow==3.4.2

forms.py

class Form():
    img = FileField()
    submit = SubmitField()

views.py

from io import StringIO
from PIL import Image
from .forms import Form

@app.route('/upload_img', methods=['GET', 'POST'])
def upload_img():
    form = Form()
    im = Image.open(StringIO(form.img.data.read())

    pass

TypeError: initial_value must be str or None, not bytes

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
rogwan
  • 177
  • 1
  • 4
  • 12

1 Answers1

7

From Pillow docs:

PIL.Image.open(fp, mode='r')

Opens and identifies the given image file. Parameters:

fp – A filename (string), pathlib.Path object or a file object. The file object must implement read(), seek(), and tell() methods, and be opened in binary mode.

What you're passing to open is a StringIO. It creates a file-like object from an str object that is opened in text mode.
The issue is caused by the argument in StringIO. form.img.data.read() returns a bytes object, passing it into the constructor is forbidden. But in your case, a StringIO won't work.
Instead, use io.BytesIO. It has pretty much the same interface, except that it takes bytes objects and returns a file-like object opened in binary mode, which is what you need.

from io import BytesIO
from PIL import Image
from .forms import Form

@app.route('/upload_img', methods=['GET', 'POST'])
def upload_img():
    form = Form()
    im = Image.open(BytesIO(form.img.data.read())

    pass
Alexis
  • 1,685
  • 1
  • 12
  • 30
illright
  • 3,991
  • 2
  • 29
  • 54
  • yes, I'vd tried with BytesIO, but still with OSError: cannot identify image file <_io.BytesIO object at 0x03B07880> – rogwan Dec 28 '16 at 01:56
  • @rogwan then the data returned from `form.img.data.read()` is not a valid image. You can test that by simply opening a file in binary mode and writing the return value there. If the image will be corrupted, then you'll have to investigate why the image data isn't transferred properly – illright Dec 28 '16 at 09:23
  • OK, thanks for your advices, open filestorage directly would be the ideal solution. – rogwan Dec 28 '16 at 14:40