I'm trying to create a view in Django, using Django REST Framework and its FileUploadParser
, where I can upload an image to, and it then stores both the original image and a thumbnail.
class ImageUploadParser(FileUploadParser):
media_type = "image/*"
class ImageUploadView(APIView):
permission_classes = (permissions.IsAuthenticated,)
parser_classes = [ImageUploadParser]
def post(self, request, filename):
if "file" not in request.data:
raise ParseError("Empty content")
file_obj = request.data["file"]
try:
img = Image.open(file_obj)
img.verify()
except UnidentifiedImageError:
raise ParseError("Unsupported image type")
path = settings.MEDIA_ROOT / f"{request.user.id}"
unique = uuid.uuid4().hex
extension = img.format.lower()
filename_full = f"{unique}.{extension}"
filename_thumb = f"{unique}.thumb.{extension}"
if not os.path.exists(path):
os.makedirs(path)
img.thumbnail((580, 580), Image.ANTIALIAS)
img.save(path / filename_thumb, "image/png", optimize=True)
return Response(f"{request.user.id}/{filename_full}", status=status.HTTP_201_CREATED)
When I post a file, this is the error I get:
Internal Server Error: /api/uploads/upload/test.png
Traceback (most recent call last):
File "/Users/kevin/Workspace/cn-django/.venv/lib/python3.10/site-packages/PIL/ImageFile.py", line 182, in load
seek = self.load_seek
File "/Users/kevin/Workspace/cn-django/.venv/lib/python3.10/site-packages/PIL/Image.py", line 529, in __getattr__
raise AttributeError(name)
AttributeError: load_seek
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/kevin/Workspace/cn-django/.venv/lib/python3.10/site-packages/asgiref/sync.py", line 486, in thread_handler
raise exc_info[1]
File "/Users/kevin/Workspace/cn-django/.venv/lib/python3.10/site-packages/django/core/handlers/exception.py", line 43, in inner
response = await get_response(request)
File "/Users/kevin/Workspace/cn-django/.venv/lib/python3.10/site-packages/django/core/handlers/base.py", line 253, in _get_response_async
response = await wrapped_callback(
File "/Users/kevin/Workspace/cn-django/.venv/lib/python3.10/site-packages/asgiref/sync.py", line 448, in __call__
ret = await asyncio.wait_for(future, timeout=None)
File "/opt/homebrew/Cellar/[email protected]/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/tasks.py", line 408, in wait_for
return await fut
File "/Users/kevin/Workspace/cn-django/.venv/lib/python3.10/site-packages/asgiref/current_thread_executor.py", line 22, in run
result = self.fn(*self.args, **self.kwargs)
File "/Users/kevin/Workspace/cn-django/.venv/lib/python3.10/site-packages/asgiref/sync.py", line 490, in thread_handler
return func(*args, **kwargs)
File "/opt/homebrew/Cellar/[email protected]/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/contextlib.py", line 79, in inner
return func(*args, **kwds)
File "/Users/kevin/Workspace/cn-django/.venv/lib/python3.10/site-packages/django/views/decorators/csrf.py", line 55, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/kevin/Workspace/cn-django/.venv/lib/python3.10/site-packages/django/views/generic/base.py", line 103, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/kevin/Workspace/cn-django/.venv/lib/python3.10/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/Users/kevin/Workspace/cn-django/.venv/lib/python3.10/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/Users/kevin/Workspace/cn-django/.venv/lib/python3.10/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/Users/kevin/Workspace/cn-django/.venv/lib/python3.10/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/kevin/Workspace/cn-django/criticalnotes/uploads/views.py", line 74, in post
img.thumbnail((580, 580), Image.ANTIALIAS)
File "/Users/kevin/Workspace/cn-django/.venv/lib/python3.10/site-packages/PIL/Image.py", line 2618, in thumbnail
im = self.resize(size, resample, box=box, reducing_gap=reducing_gap)
File "/Users/kevin/Workspace/cn-django/.venv/lib/python3.10/site-packages/PIL/Image.py", line 2156, in resize
self.load()
File "/Users/kevin/Workspace/cn-django/.venv/lib/python3.10/site-packages/PIL/ImageFile.py", line 185, in load
seek = self.fp.seek
AttributeError: 'NoneType' object has no attribute 'seek'
I am not sure what is going wrong, what is None
, because img
is not None
at least.
This is because Pillow's verify()
function closes the underlying file descriptor, after which functions like seek
no longer exist internally.
You will need to use PIL.Image.open()
to open the Image
again before calling save()
.
For reference, see: