Почему при отправке ответа на создание FileResponse в Django возвращается ошибка разрешения?
В папке temp находится временный файл video.mp4, который должен быть создан, затем отправлен пользователю как вложение, а затем удален. Следующий код возвращает PermissionError: [WinError 32]
для этой строки: os.remove(file_path)
. Почему?
def download_video(request):
if request.method == 'POST':
link_input_data = request.POST.get('link_input_field') # todo change to use django forms later
download_cda.start_download(link_input_data)
file_path = "temp\\" + "video.mp4"
response = None
try:
file = open(file_path, "rb")
response = FileResponse(file, as_attachment=True, filename="video.mp4")
except Exception as e:
print(e) # todo add exception code
finally:
os.remove(file_path)
return response
else:
form = UrlForm()
return render(request, 'index.html', {"url_form": form})
Я не смог найти ничего об этом в документации: [FileResponse] (https://docs.djangoproject.com/en/5.0/ref/request-response/#django.http.FileResponse)
Почему? Я слишком рано удаляю файл?
Да, потому что FileResponse
[Django-doc] работает потоковым образом: он читает фрагмент файла, передает его клиенту, затем читает следующий фрагмент и т.д. Если вы возвращаете ответ, значит, файл еще не полностью прочитан.
Мы можем использовать список _resource_closers
в ответе, чтобы удалить файл:
def download_video(request):
if request.method == 'POST':
link_input_data = request.POST.get(
'link_input_field'
) # todo change to use django forms later
download_cda.start_download(link_input_data)
file_path = 'temp\\' + 'video.mp4'
response = None
def closer():
return os.remove(file_path)
try:
response = FileResponse(
open(file_path, 'rb'), as_attachment=True, filename='video.mp4'
)
response._resource_closers.append(closer)
return response
except Exception as e:
print(e) # todo add exception code
closer()
form = UrlForm()
return render(request, 'index.html', {'url_form': form})
But serving files with Django is however often not a good idea. Usually what you do is let the webserver like Nginx or Apache serve the file. For Nginx with an X-Accel-Redirect header [nginx-doc].
В этом случае вы можете даже добавить post_action
в nginx, чтобы удалить файл после того, как Nginx обслужил его.