Opened 2 years ago

Closed 2 years ago

Last modified 2 years ago

#33965 closed Cleanup/optimization (fixed)

Improve docs for PIL validation of ImageField

Reported by: Timothy Schilling Owned by: Alex Morega
Component: Documentation Version: 4.1
Severity: Normal Keywords: documentation imagefield
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The current docs indicate:

You may also provide any file-like object (e.g., StringIO or BytesIO) as a file handle. If you’re uploading to an ImageField, the object needs a name attribute that passes the validate_image_file_extension validator. For example:

from io import BytesIO
img = BytesIO(b'mybinarydata')
img.name = 'myimage.jpg'

However, this results in the invalid_image error for ImageField when PIL is installed. Some possible code to pass this validation is:

img = BytesIO()
Image.new("RGB", (1, 1), "#FF0000").save(img, format='PNG')
img.name = 'myimage.png'
img.seek(0)

This creates the binary data that's actually an image which passes the underlying PIL.Image.verify() call.

Change History (8)

comment:1 by Alex Morega, 2 years ago

FWIW, the call to Image.new(...).save(...) looks distracting to me, and makes the example hard to read. PIL can read the 35-byte GIF from this StackOverflow answer: https://stackoverflow.com/a/15960901. I think it works better as an example because it's just a blob of binary.

>>> from io import BytesIO
>>> from PIL import Image
>>> img = BytesIO(
...     b'GIF89a\x01\x00\x01\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\x00'
...     b'\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x01\x00\x00'
... )
>>> img.name = 'myimage.gif'
>>> pil_image = Image.open(img)
>>> pil_image
<PIL.GifImagePlugin.GifImageFile image mode=L size=1x1 at 0xFFFF9392BF40>
>>> pil_image.verify()

comment:2 by Mariusz Felisiak, 2 years ago

Triage Stage: UnreviewedAccepted
Type: UncategorizedCleanup/optimization

Thanks for the ticket. Agreed, we should improve this example and use a real image in BytesIO(). I'd prefer Alex's proposition, to avoid unnecessary distraction.

comment:3 by Alex Morega, 2 years ago

Has patch: set
Owner: changed from nobody to Alex Morega
Status: newassigned

comment:4 by Mariusz Felisiak, 2 years ago

Triage Stage: AcceptedReady for checkin

comment:5 by Mariusz Felisiak <felisiak.mariusz@…>, 2 years ago

Resolution: fixed
Status: assignedclosed

In 838cc0f:

Fixed #33965 -- Improved file-like object example of ImageField in docs.

This uses a valid image.

comment:6 by Mariusz Felisiak <felisiak.mariusz@…>, 2 years ago

In 27ad94ab:

[4.1.x] Fixed #33965 -- Improved file-like object example of ImageField in docs.

This uses a valid image.

Backport of 838cc0f449f96c157cb44eb91984a2753edc7f42 from main

comment:7 by Timothy Schilling, 2 years ago

Is there any concern that users will be running random byte code? This on the face of it, looks like code that should not be blindly copied and pasted into a codebase because it's difficult to parse what the following actually is. Using PIL to generate an image is more declarative and explicit in what it's doing.

>>> img = BytesIO(
...     b'GIF89a\x01\x00\x01\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\x00'
...     b'\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x01\x00\x00'
... )

comment:8 by Mariusz Felisiak, 2 years ago

This is a part of the testing tools docs, so I think we don't need to be so precaution 🤔.

Note: See TracTickets for help on using tickets.
Back to Top