在将 Python、Django 和 Alpine 升级到最新版本时偶然发现了这个错误......这是一个奇怪的错误。 当我上传大于 FILE_UPLOAD_MAX_MEMORY_SIZE(设置为 5MB)的文件时,会发生错误。
我设置了两个开发环境。
此错误仅在 Docker 环境下且仅当文件超过最大内存大小时发生。在所有其他情况下,上传都可以工作 - 即使文件超出本地开发服务器上的内存限制。
错误:
Saving new order file to: customer_name/_web_portal/PendingOrders/7935/zip_03.zip
Internal Server Error: /b2b_api/orders/
Traceback (most recent call last):
File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 56, in wrapper_view
return view_func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/rest_framework/viewsets.py", line 125, in view
return self.dispatch(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/code/api/views.py", line 352, in dispatch
return super().dispatch(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/usr/local/lib/python3.11/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/usr/local/lib/python3.11/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/rest_framework/mixins.py", line 19, in create
self.perform_create(serializer)
File "/code/api/views.py", line 375, in perform_create
serializer.save()
File "/usr/local/lib/python3.11/site-packages/rest_framework/serializers.py", line 212, in save
self.instance = self.create(validated_data)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/code/api/serializers.py", line 286, in create
instance = super().create(validated_data)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/code/api/serializers.py", line 125, in create
db_file.save()
File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 814, in save
self.save_base(
File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 877, in save_base
updated = self._save_table(
^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 1020, in _save_table
results = self._do_insert(
^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 1061, in _do_insert
return manager._insert(
^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/db/models/manager.py", line 87, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/db/models/query.py", line 1805, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/db/models/sql/compiler.py", line 1821, in execute_sql
for sql, params in self.as_sql():
^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/db/models/sql/compiler.py", line 1745, in as_sql
value_rows = [
^
File "/usr/local/lib/python3.11/site-packages/django/db/models/sql/compiler.py", line 1746, in <listcomp>
[
File "/usr/local/lib/python3.11/site-packages/django/db/models/sql/compiler.py", line 1747, in <listcomp>
self.prepare_value(field, self.pre_save_val(field, obj))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/db/models/sql/compiler.py", line 1695, in pre_save_val
return field.pre_save(obj, add=True)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/db/models/fields/files.py", line 317, in pre_save
file.save(file.name, file.file, save=False)
File "/usr/local/lib/python3.11/site-packages/django/db/models/fields/files.py", line 93, in save
self.name = self.storage.save(name, content, max_length=self.field.max_length)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/core/files/storage/base.py", line 38, in save
name = self._save(name, content)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/core/files/storage/filesystem.py", line 130, in _save
os.chmod(full_path, self.file_permissions_mode)
FileNotFoundError: [Errno 2] No such file or directory: '/sftp/customer_name/_web_portal/PendingOrders/7935/zip_03.zip'
奇怪的是,当我查看文件夹时,文件就在那里。 Apache 运行的用户可以访问它。
尝试检查
inotifywait
发生了什么,这是上传目录的输出:
Setting up watches. Beware: since -r was given, this may take a while!
Watches established.
/sftp/customer_name/_web_portal/PendingOrders/ CREATE,ISDIR 7982
/sftp/customer_name_web_portal/PendingOrders/ OPEN,ISDIR 7982
/sftp/customer_name/_web_portal/PendingOrders/ ACCESS,ISDIR 7982
/sftp/customer_name/_web_portal/PendingOrders/ CLOSE_NOWRITE,CLOSE,ISDIR 7982
# --> between those two records the error is thrown
/sftp/customer_name/_web_portal/PendingOrders/7982/ CLOSE_WRITE,CLOSE zip_02.zip
还尝试在错误发生之前编辑 django 文件(就在
os.chmod
...之前)并打印文件是否存在,这是输出:
os.listdir(directory)=['zip_10MB.zip']
os.path.exists(full_path)=False
os.path.isfile(full_path)=False
repr(full_path)="'/sftp/customer_name/_web_portal/PendingOrders/8013/zip_10MB.zip'" repr(directory)="'/sftp/customer_name/_web_portal/PendingOrders/8013'"
这对我来说是不真实的,因为 listdir 输出该文件夹中有一个文件,但
os.path.exists
输出 False?!
我发现 os.path.exists()
和 isfile
在下面调用 os.stat()
来查找必要的信息,...所以我尝试了 os.stat(full_path)
但失败并出现 FileNotFoundError。
抛出错误后,我使用运行 Apache 的同一用户登录 Docker,并尝试在所述文件路径上运行
os.stat()
,它返回 OK(文件信息)。
我还检查了 Django 将文件从临时目录移动到最终目的地时使用的操作 - 它是 django/core/files/move.py file_move_safe 函数 - 而且它是一个简单的
os.rename()
我尝试的下一步是将
time.sleep()
放在实际错误之前,并将 cd
-ing 放在上传目录中,并对每个用户执行 ls
命令,这是输出:
根用户:
total 10432
drwxrwx--- 1 web_port web_port 512 Aug 17 09:48 .
drwxrwx--- 1 web_port web_port 512 Aug 17 09:48 ..
-rw------- 1 web_port web_port 10679630 Aug 17 09:48 zip_10MB.zip
web_portal(apache / 应用程序)用户:
ls: ./zip_10MB.zip: No such file or directory
total 0
drwxrwx--- 1 web_port web_port 512 Aug 17 09:48 .
drwxrwx--- 1 web_port web_port 512 Aug 17 09:48 ..
Ps:我正在使用
python:3.11-alpine
Docker 镜像(Docker Desktop),以及 Django==4.2.4
和 djangorestframework==3.14.0
。
更新: 尝试将我的 Docker 映像/容器放置在 Linux 操作系统上 - 文件上传工作没有问题。所以我猜测 Windows 版 Docker 出了问题,或者 Windows 上处理“绑定”挂载的方式出了问题。也许?
更新#2: 知道文件是否被 Windows Defender 或其他东西锁定。我不知道我已经没有主意了。所以我禁用了 Windows Defender,在文件夹上添加了例外,..错误仍然存在。接下来,我尝试在文件夹上启用 Windows 审核日志记录,但我不知道如何从安全日志的输出中理解。
有谁知道问题可能是什么,或者我接下来可以尝试什么来进一步限制此问题的原因?
尝试在您的
MAX_UPLOADING_FILE_SIZE
文件中设置 settings.py
,此解决方案可以帮助我完成我的项目:
MAX_UPLOADING_FILE_SIZE = 31457280 # 30 MB