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.
--
Ticket URL: <https://code.djangoproject.com/ticket/33965>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
Comment (by Alex Morega):
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.
{{{#!python
>>> 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()
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/33965#comment:1>
* type: Uncategorized => Cleanup/optimization
* stage: Unreviewed => Accepted
Comment:
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.
--
Ticket URL: <https://code.djangoproject.com/ticket/33965#comment:2>
* owner: nobody => Alex Morega
* status: new => assigned
* has_patch: 0 => 1
Comment:
[https://github.com/django/django/pull/16018 PR].
--
Ticket URL: <https://code.djangoproject.com/ticket/33965#comment:3>
* stage: Accepted => Ready for checkin
--
Ticket URL: <https://code.djangoproject.com/ticket/33965#comment:4>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"838cc0f449f96c157cb44eb91984a2753edc7f42" 838cc0f]:
{{{
#!CommitTicketReference repository=""
revision="838cc0f449f96c157cb44eb91984a2753edc7f42"
Fixed #33965 -- Improved file-like object example of ImageField in docs.
This uses a valid image.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/33965#comment:5>
Comment (by Mariusz Felisiak <felisiak.mariusz@…>):
In [changeset:"27ad94ab3b0d4f5da74b10c4d5e768070139ec77" 27ad94ab]:
{{{
#!CommitTicketReference repository=""
revision="27ad94ab3b0d4f5da74b10c4d5e768070139ec77"
[4.1.x] Fixed #33965 -- Improved file-like object example of ImageField in
docs.
This uses a valid image.
Backport of 838cc0f449f96c157cb44eb91984a2753edc7f42 from main
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/33965#comment:6>
Comment (by Timothy Schilling):
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'
... )
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/33965#comment:7>
Comment (by Mariusz Felisiak):
This is a part of the testing tools docs, so I think we don't need to be
so precaution 🤔.
--
Ticket URL: <https://code.djangoproject.com/ticket/33965#comment:8>