You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django上传图片时Pillow报AttributeError: 'NoneType'无seek属性

问题:Django DRF FileUploadParser 处理图片时出现 AttributeError: 'NoneType' object has no attribute 'seek'

我尝试使用Django及Django REST Framework的FileUploadParser创建图片上传视图,实现上传图片并同时存储原图与缩略图的功能,但提交文件时出现错误。

代码实现

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)

报错信息

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/python@3.10/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/python@3.10/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'

问题原因

调用img.verify()后,PIL会将文件指针移动到文件末尾,并且关闭了对原始文件对象的引用,导致img对象内部的fp属性变为None。后续调用img.thumbnail()时,PIL需要重新读取文件内容,但无法访问已失效的文件指针,从而抛出错误。

解决方法

方法1:重置文件指针并重新加载图片

在verify()之后,将文件指针重置到开头,然后重新打开图片:

try:
    img = Image.open(file_obj)
    img.verify()
    # 重置文件指针到文件开头
    file_obj.seek(0)
    # 重新加载图片
    img = Image.open(file_obj)
except UnidentifiedImageError:
    raise ParseError("Unsupported image type")

方法2:将文件内容读入内存(更可靠)

先把文件内容读取到内存中的BytesIO对象,避免文件指针移动的问题:

from io import BytesIO

# ...

file_obj = request.data["file"]
# 读取文件内容到内存
file_content = file_obj.read()

try:
    img = Image.open(BytesIO(file_content))
    img.verify()
    # 重新用内存中的内容创建图片对象
    img = Image.open(BytesIO(file_content))
except UnidentifiedImageError:
    raise ParseError("Unsupported image type")

补充:保存原图

你的代码中只实现了缩略图的保存,建议添加原图的保存逻辑:

# 保存原图
img_full = Image.open(BytesIO(file_content)) # 对应方法2的实现
img_full.save(path / filename_full, extension.upper(), optimize=True)

内容的提问来源于stack exchange,提问作者Kevin Renskers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 03:08:12