Django PIL:IOError无法识别图像文件

时间:2022-06-28 08:35:44

I'm learning Python and Django.

我正在学习Python和Django。

An image is provided by the user using forms.ImageField(). Then I have to process it in order to create two different sized images.

用户使用forms.ImageField()提供图像。然后我必须处理它以创建两个不同大小的图像。

When I submit the form, Django returns the following error:

当我提交表单时,Django返回以下错误:

IOError at /add_event/
cannot identify image file

I call the resize function:

我调用resize函数:

def create_event(owner_id, name, image):         
    image_thumb = image_resizer(image, name, '_t', 'events', 180, 120)  
    image_medium = image_resizer(image, name, '_m', 'events', 300, 200)

I get en error when image_resizer is called for the second time:

第二次调用image_resizer时出错:

def image_resizer(image, name, size, app_name, length, height): 
    im = Image.open(image)
    if im.mode != "RGB":
        im = im.convert("RGB")
    im = create_thumb(im, length, height)
    posit = str(MEDIA_ROOT)+'/'+app_name+'/'
    image_2 = im
    image_name = name + size +'.jpg' 
    imageurl = posit + image_name
    image_2.save(imageurl,'JPEG',quality=80)
    url_image='/'+app_name+'/'+image_name  
    return url_image

Versions:
Django 1.3.1
Python 2.7.1
PIL 1.1.7

版本:Django 1.3.1 Python 2.7.1 PIL 1.1.7

I'm trying to find the problem, but i don't know what to do. Thank you in advanced!

我试图找到问题,但我不知道该怎么做。先谢谢你!

EDIT
I solved rewriting the function; now it creates the different images in batch:

编辑我解决了重写功能;现在它批量创建不同的图像:

I call the resize function:

我调用resize函数:

url_array = image_resizer.resize_batch(image, image_name, [[180,120,'_t'], [300,200,'_m']], '/events/')  

so:

所以:

image_thumb = url_array[0]
image_medium = url_array[1]

and the resize function:

和调整大小功能:

def resize_batch(image, name, size_array, position):
    im = Image.open(image)
    if im.mode != "RGB":
        im = im.convert("RGB")
    url_array = []
    for size in size_array:
        new_im = create_thumb(im, size[0], size[1])
        posit = str(MEDIA_ROOT) + position
        image_name = name + size[2] +'.jpg' 
        imageurl = posit + image_name
        new_im.save(imageurl,'JPEG',quality=90)
        new_url_array = position + image_name
        url_array.append(new_url_array)
    return url_array

Thanks to all!

谢谢大家!

2 个解决方案

#1


19  

As ilvar asks in the comments, what kind of object is image? I'm going to assume for the purposes of this answer that it's the file property of a Django ImageField that comes from a file uploaded by a remote user.

正如ilvar在评论中所说,图像是什么样的对象?为了这个答案的目的,我将假设它是来自远程用户上传的文件的Django ImageField的文件属性。

After a file upload, the object you get in the ImageField.file property is a TemporaryUploadedFile object that might represent a file on disk or in memory, depending on how large the upload was. This object behaves much like a normal Python file object, so after you have read it once (to make the first thumbnail), you have reached the end of the file, so that when you try to read it again (to make the second thumbnail), there's nothing there, hence the IOError. To make a second thumbnail, you need to seek back to the beginning of the file. So you could add the line

上传文件后,您在ImageField.file属性中获得的对象是TemporaryUploadedFile对象,该对象可能表示磁盘或内存中的文件,具体取决于上载的大小。这个对象的行为很像普通的Python文件对象,所以在你读完一次之后(制作第一个缩略图),你已到达文件的末尾,这样当你再次尝试读取它时(制作第二个缩略图) ),没有任何东西,因此IOError。要制作第二个缩略图,您需要回到文件的开头。所以你可以添加这条线

image.seek(0)

to the start of your image_resizer function.

到image_resizer函数的开头。

But this is unnecessary! You have this problem because you are asking the Python Imaging Library to re-read the image for each new thumbnail you want to create. This is a waste of time: better to read the image just once and then create all the thumbnails you want.

但这是不必要的!您遇到此问题是因为您要求Python Imaging Library重新读取您要创建的每个新缩略图的图像。这是浪费时间:最好只读取一次图像,然后创建所需的所有缩略图。

#2


-2  

I'm guessing that is a TemporaryUploadedFile ... find this with type(image).

我猜这是一个TemporaryUploadedFile ...用类型(图像)找到它。

import cStringIO

if isinstance(image, TemporaryUploadedFile):
    temp_file = open(image.temporary_file_path(), 'rb+')
    content = cStringIO.StringIO(temp_file.read())
    image = Image.open(content)
    temp_file.close()

I'm not 100% sure of the code above ... comes from 2 classes I've got for image manipulation ... but give it a try.

我不是百分之百确定上面的代码......来自我为图像处理而设的2个类......但试一试。

If is a InMemoryUploadedFile your code should work!

如果是InMemoryUploadedFile你的代码应该工作!

#1


19  

As ilvar asks in the comments, what kind of object is image? I'm going to assume for the purposes of this answer that it's the file property of a Django ImageField that comes from a file uploaded by a remote user.

正如ilvar在评论中所说,图像是什么样的对象?为了这个答案的目的,我将假设它是来自远程用户上传的文件的Django ImageField的文件属性。

After a file upload, the object you get in the ImageField.file property is a TemporaryUploadedFile object that might represent a file on disk or in memory, depending on how large the upload was. This object behaves much like a normal Python file object, so after you have read it once (to make the first thumbnail), you have reached the end of the file, so that when you try to read it again (to make the second thumbnail), there's nothing there, hence the IOError. To make a second thumbnail, you need to seek back to the beginning of the file. So you could add the line

上传文件后,您在ImageField.file属性中获得的对象是TemporaryUploadedFile对象,该对象可能表示磁盘或内存中的文件,具体取决于上载的大小。这个对象的行为很像普通的Python文件对象,所以在你读完一次之后(制作第一个缩略图),你已到达文件的末尾,这样当你再次尝试读取它时(制作第二个缩略图) ),没有任何东西,因此IOError。要制作第二个缩略图,您需要回到文件的开头。所以你可以添加这条线

image.seek(0)

to the start of your image_resizer function.

到image_resizer函数的开头。

But this is unnecessary! You have this problem because you are asking the Python Imaging Library to re-read the image for each new thumbnail you want to create. This is a waste of time: better to read the image just once and then create all the thumbnails you want.

但这是不必要的!您遇到此问题是因为您要求Python Imaging Library重新读取您要创建的每个新缩略图的图像。这是浪费时间:最好只读取一次图像,然后创建所需的所有缩略图。

#2


-2  

I'm guessing that is a TemporaryUploadedFile ... find this with type(image).

我猜这是一个TemporaryUploadedFile ...用类型(图像)找到它。

import cStringIO

if isinstance(image, TemporaryUploadedFile):
    temp_file = open(image.temporary_file_path(), 'rb+')
    content = cStringIO.StringIO(temp_file.read())
    image = Image.open(content)
    temp_file.close()

I'm not 100% sure of the code above ... comes from 2 classes I've got for image manipulation ... but give it a try.

我不是百分之百确定上面的代码......来自我为图像处理而设的2个类......但试一试。

If is a InMemoryUploadedFile your code should work!

如果是InMemoryUploadedFile你的代码应该工作!