Django + Gunicorn + Nginx + Python -> Ссылка для загрузки файла с веб-сервера
На моей веб-странице, обслуживаемой веб-сервером Debian, размещенным на amazon-lightsail за nginx и gunicorn, пользователь может послать запрос на запуск функции представления Django. Эта функция добавляет некоторую работу в фоновый процесс и каждые 5 с проверяет, создал ли фоновый процесс файл. Если файл существует, представление посылает ответ, и пользователь может скачать файл. Иногда этот процесс может занять много времени, и пользователь получает сообщение 502 bad gateway. Если процесс занимает слишком много времени, я хочу отправить пользователю электронное письмо со ссылкой, по которой он может скачать файл с веб-сервера. Я знаю, как отправить письмо после завершения процесса, но не знаю, как передать файл пользователю по ссылке для скачивания.
Это конец моей функции просмотра :
print('######### Serve Downloadable File #########')
while not os.path.exists(f'/srv/data/ship_notice/{user_token}'):
print('wait on file is servable')
time.sleep(5)
# Open the file for reading content
path = open(filepath, 'r')
# Set the mime type
mime_type, _ = mimetypes.guess_type(filepath)
# Set the return value of the HttpResponse
response = HttpResponse(path, content_type=mime_type)
# Set the HTTP header for sending to browser
response['Content-Disposition'] = f"attachment; filename={filename}"
# Return the response value
return response
Другая модель функции, которая отправляет почту пользователю после завершения процесса:
def send_mail_precipitation(filepath, user_token, email):
from django.core.mail import EmailMessage
import time
import os
while not os.path.exists(f'/srv/data/ship_notice/{user_token}'):
print('wait 30secs')
time.sleep(30)
msg = EmailMessage(
subject = 'EnviAi data',
body = 'The process is finished, you can download the file here.... ',
to = [email]
)
msg.send()
Файл слишком большой, чтобы отправить его с помощью msg.attach_file(filepath)
Какие у меня есть варианты, чтобы послать пользователю ссылку для загрузки этих файлов. Нужно ли мне устанавливать ftp-сервер/папку, или какие у меня есть варианты? И какую работу мне нужно проделать, если я хочу, чтобы ссылка была действительна только 72 часа? Большое спасибо!
Не прямой ответ, но возможный путь.
Такие длительно выполняющиеся задачи обычно реализуются с помощью дополнительного инструмента, такого как Celery. Плохая практика - позволять конечной точке view/api работать столько, сколько потребуется, и заставлять запрашивающий процесс ждать завершения. Хорошей практикой является предоставление ответа так быстро, как вы можете.
В вашем случае это будет:
- создайте задачу celery для сборки вашего файла (создание задачи происходит быстро)
- возвращает идентификатор задачи в ответ
- запросите статус задачи из фронтенда с заданным идентификатором задачи
- после выполнения задания должен быть возвращен URL файла
Также можно добавить код on_success, который будет выполнен (запущен Celery автоматически), когда задача будет выполнена. Вы можете вызвать свою email_user_when_file_is_ready
функцию в реакции на это событие.
Чтобы сделать файлы доступными для загрузки, вы можете добавить местоположение в конфигурацию nginx, как вы это делали для статических и медиа папок. Поместите ваши файлы в папку с привязкой к местоположению и все. Дайте пользователю URL вашего файла.