当用户尝试注册我的网站并上传照片时,我收到FileNotFoundError
错误消息。错误消息如下:
[Errno 2] No such file or directory: '/tmp/<file_name>.upload.jpg'
<file_name>
是随机文件名。
最近我收到了一些类似的消息,这些用户无法上传照片并完成注册(用户必须拥有个人资料照片才能成为Speedy Match的活跃成员)。你知道是什么问题吗?我正在将Django 2.1.15与Python 3.6.8配合使用。
我现在使用Chrome和Firefox进行了检查,并能够注册到我的网站并上传照片。注册网站的大多数用户都成功上传了照片。但是最近对某些特定用户失败了。
以下是一些代码:
def clean_photo(self):
photo = self.files.get('photo')
if (photo):
speedy_match_accounts_validators.validate_photo_for_user(user=self.instance.user, photo=photo)
else:
photo = self.instance.user.photo
speedy_match_accounts_validators.validate_photo_for_user(user=self.instance.user, photo=photo, test_new_photo=False)
return self.cleaned_data
def save(self, commit=True):
if (commit):
if ('photo' in self.fields):
if (self.files):
user_image = Image(owner=self.instance.user, file=self.files['photo'])
user_image.save()
self.instance.user.photo = user_image
for field_name in self.user_fields:
if (field_name in self.fields):
setattr(self.instance.user, field_name, self.cleaned_data[field_name])
self.instance.user.save()
super().save(commit=commit)
def validate_photo_for_user(user, photo, test_new_photo=True):
validate_photo(photo=photo)
if (test_new_photo):
user._photo = user.photo
photo_is_valid = False
try:
if (test_new_photo):
user_image = Image(owner=user, file=photo)
user_image.save()
user.photo = user_image
profile_picture_html = render_to_string(template_name="accounts/tests/profile_picture_test.html", context={"user": user})
logger.debug('validate_photo_for_user::user={user}, profile_picture_html={profile_picture_html}'.format(
user=user,
profile_picture_html=profile_picture_html,
))
if (not ('speedy-core/images/user.svg' in profile_picture_html)):
photo_is_valid = True
except:
photo_is_valid = False
if (test_new_photo):
user.photo = user._photo
try:
user_image.delete()
except:
pass
if (not (photo_is_valid)):
raise ValidationError(_("You can't use this format for your profile picture. Only JPEG or PNG formats are accepted."))
可以在GitHub上看到网站的代码。
以下是我通过电子邮件收到的详细信息:
FileNotFoundError at /registration-step-2/
[Errno 2] No such file or directory: '/tmp/....upload.jpg' (I removed the file name)
Request Method: POST
Request URL: https://he.speedymatch.com/registration-step-2/
Django Version: 2.1.15
Exception Type: FileNotFoundError
Exception Value:
[Errno 2] No such file or directory: '/tmp/....upload.jpg' (I removed the file name)
Exception Location: .../site-packages/django/core/files/move.py in file_move_safe, line 56 (I removed the path)
Python Executable: /usr/bin/uwsgi-core
Python Version: 3.6.8
我也收到了很多变量的回溯,但是太个人化了,无法在此网站上分享。
回溯包含以下几行:
self.object = form.save()
user_image.save()
return super().save(*args, **kwargs)
return super().save(*args, **kwargs)
return super().save(*args, **kwargs)
force_update=force_update, update_fields=update_fields)
self._save_parents(cls, using, update_fields)
self._save_table(cls=parent, using=using, update_fields=update_fields)
for f in non_pks]
for f in non_pks]
file.save(file.name, file.file, save=False)
self.name = self.storage.save(name, content, max_length=self.field.max_length)
return self._save(name, content)
file_move_safe(content.temporary_file_path(), full_path)
with open(old_file_name, 'rb') as old_file:
答案 0 :(得分:3)
仅当文件大小大于2.5 MB时,该错误才可重现:
# Maximum size, in bytes, of a request before it will be streamed to the
# file system instead of into memory.
FILE_UPLOAD_MAX_MEMORY_SIZE = 2621440 # i.e. 2.5 MB
为防止错误,您可以执行以下操作之一:
/tmp
目录的权限,并在可能的情况下授予访问权限。FILE_UPLOAD_TEMP_DIR
设置为文件系统用户可以在其中写入和读取的目录。如果Python的NamedTemporaryFile
无法取消链接,则应定期清除此内容。答案 1 :(得分:1)
设置中的这一行至少可以暂时解决此问题:
FILE_UPLOAD_MAX_MEMORY_SIZE = int(15 * 1024 * 1024) # 15 MB
user_image.save()
被调用两次-一次用于验证图片,然后再次将其保存为用户的个人资料图片(如果有效)。如果文件大小大于FILE_UPLOAD_MAX_MEMORY_SIZE
字节(默认为2.5 MB),则会导致错误。一次调用user_image.save()
将解决此问题。
我修复了代码,这是有效的代码。每个文件仅保存一次:
def clean_photo(self):
photo = self.files.get('photo')
if (photo):
user_image = Image(owner=self.instance.user, file=photo)
user_image.save()
self.instance.user._new_photo = user_image
speedy_match_accounts_validators.validate_photo_for_user(user=self.instance.user, photo=photo, test_new_photo=True)
else:
photo = self.instance.user.photo
speedy_match_accounts_validators.validate_photo_for_user(user=self.instance.user, photo=photo, test_new_photo=False)
return self.cleaned_data
def save(self, commit=True):
if (commit):
if ('photo' in self.fields):
photo = self.files.get('photo')
if (photo):
self.instance.user.photo = self.instance.user._new_photo
for field_name in self.user_fields:
if (field_name in self.fields):
setattr(self.instance.user, field_name, self.cleaned_data[field_name])
self.instance.user.save()
super().save(commit=commit)
def validate_photo_for_user(user, photo, test_new_photo):
validate_photo(photo=photo)
if (test_new_photo):
user._photo = user.photo
photo_is_valid = False
try:
if (test_new_photo):
user.photo = user._new_photo
profile_picture_html = render_to_string(template_name="accounts/tests/profile_picture_test.html", context={"user": user})
logger.debug('validate_photo_for_user::user={user}, profile_picture_html={profile_picture_html}'.format(
user=user,
profile_picture_html=profile_picture_html,
))
if (not ('speedy-core/images/user.svg' in profile_picture_html)):
photo_is_valid = True
except:
photo_is_valid = False
if (test_new_photo):
user.photo = user._photo
if (not (photo_is_valid)):
raise ValidationError(_("You can't use this format for your profile picture. Only JPEG or PNG formats are accepted."))
使用此代码,我可以将FILE_UPLOAD_MAX_MEMORY_SIZE
保留为默认值(2.5 MB)或任何值。目前,我将其设置为7.5 MB。