Search code examples
python-3.xdjangodjango-modelsiopython-imaging-library

How to create InMemoryUploadedFile objects proper in django


I'm using a python function to resize user uploaded images in Django. I use BytesIO() and InMemoryUploadedFile() classes to convert pillow object to Django UplodedFile and save it in the model. here how I instantiate InMemoryUploadedFile object

from PIL import Image
import io
import PIL
import sys
from django.core.files.uploadedfile import InMemoryUploadedFile


def image_resize(image,basewidth):
    img_io = io.BytesIO()
    img = Image.open(image)
    percent = (basewidth / float(img.size[0]))
    hsize = int(float(img.size[1]) * percent)
    img = img.resize((basewidth, hsize),PIL.Image.ANTIALIAS)
      
    img.save(img_io, format="JPEG")
        
    new_pic= InMemoryUploadedFile(img_io, 
            'ImageField',
            'profile_pic',
            'JPEG',
            sys.getsizeof(img_io), None)
    return new_pic

but this resize the image and it does not save the file as a jpeg it saves the file with the type of File but when to replace the filename with profile_pic.jpg it saves with the type of jpeg. why this happens


Solution

  • The field_name parameter in InMemoryUploadedFile(file, field_name, name, content_type, size, charset) requires the full filename including the file extension for reasons the official documentation does not list. Here is a link giving some sample usage of InMemoryUploadedFile (look at example 8)

    Getting the file extension should be easy when using os.path.splitext like so:

    def image_resize(image,basewidth):
        img_io = io.BytesIO()
        img = Image.open(image)
        img_ext = list(os.path.splitext(img.filename))[-1]
        percent = (basewidth / float(img.size[0]))
        hsize = int(float(img.size[1]) * percent)
        img = img.resize((basewidth, hsize),PIL.Image.ANTIALIAS)
        img.save(img_io, format="JPEG")
            
        new_pic= InMemoryUploadedFile(img_io, 
                'ImageField',
                'profile_pic' + img_ext,
                'JPEG',
                sys.getsizeof(img_io), None)
        return new_pic