Функция выдает ошибку SuspiciousFileOperation
В Django-проекте есть функция:
def create_docs(medic_id: str, context: dict, type_in: str) -> str:
if type_in == 'zayavlenie':
template = f'{BASE_DIR}/static/templates_docs/shablon_zayavleniya.docx'
elif type_in == 'portfolio':
template = f'{BASE_DIR}/static/templates_docs/shablon_portfolio.docx'
elif type_in == 'otchet':
template = f'{BASE_DIR}/static/templates_docs/shablon_otcheta.docx'
elif type_in == 'pamyatka':
template = f'{BASE_DIR}/static/templates_docs/shablon_pamyatky.docx'
else:
raise ValueError(f'Некорректное значение type_in: {type_in}')
doc = DocxTemplate(template)
doc.render(context)
file_name = f"{BASE_DIR}/docs/{type_in}.docx"
doc.save(file_name)
medic = get_object_or_404(Medic, id=medic_id)
if type_in == 'zayavlenie':
with open(file_name, 'rb') as f:
medic.statement.save(file_name, File(f))
if type_in == 'portfolio':
with open(file_name, 'rb') as f:
medic.portfolio.save(file_name, File(f))
if type_in == 'otchet':
with open(file_name, 'rb') as f:
medic.report.save(file_name, File(f))
if type_in == 'pamyatka':
with open(file_name, 'rb') as f:
medic.readme.save(file_name, File(f))
return
Функция принимает 4 docx шаблона, и словарь context . На выходе формирует 4 файла с подставленными данными из словаря, плюс формирует ссылку и прикрепляет ее к полю модели, которые заданы следующим образом:
class Medic(models.Model):
statement = models.FileField(blank=True)
portfolio = models.FileField(blank=True)
report = models.FileField(blank=True)
readme = models.FileField(blank=True)
Я не до конца понимаю как работает эта функция, собрал этот компот по ответам из интернета. На локальном компьютере она сделает так (на примере одного файла из 4-х): Обращение 1-го пользователя:
- Формирует файл
otchet.docx - Формирует файл
otchet_0uUIBFc.docx - Записывает ссылку на
otchet_0uUIBFc.docxв полеmedic.report
Обращение 2-го пользователя:
- Перезаписывает файл
otchet.docx - Формирует файл otchet_CT52ndN.docx
- Записывает ссылку на
otchet_CT52ndN.docxв полеmedic.reportИ так далее.
Сейчас я переношу проект на хостинг, и на хостинге джанго категорически ругается на эту функцию. Ошибка такая: SuspiciousFileOperation at /form/done/ Detected path traversal attempt in '/home/c/cz33441/med_site/public_html/accreditation/docs/otchet.docx' И я совсем не понимаю в чем может быть дело. Посоветуйте пожалуйста как устранить эту ошибку, либо как лучше реализовать эту функцию. Очевидно, что решение так себе, но ничего лучше не могу придумать.
Ответы (2 шт):
Вот ответ на английском СО. Если вкратце, то не нужно писать ничего в те каталоги, где лежит сайт, это опасная практика по многим причинам, поэтому Django и ругается. Писать можно во временные файлы, расположенные в специально отведённых для временных файлов местах. Для этого в Django есть специальные методы.
Если кому-то поможет, то я решила эту проблему тем, что заменила абсолютные пути при сохранении файла на относительные. Вот как выглядел мой MEDIA_ROOT:
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Я просто заменила на:
MEDIA_ROOT = 'media'
Так формирую путь для сохранения файла:
os.path.join(settings.MEDIA_ROOT, filename)
Судя по вашей ошибке, вы тоже используете абсолютные пути при сохранении.