Django сломанный ответ с файловыми данными
В моем проекте я использую AWS S3 Bucket для медиа файлов. Проект содержит приложение media_app, которое обеспечивает get и post запросы к файлам в удаленном хранилище (все запросы проходят через сервер, поэтому media_app является своего рода прокси между фронтендом и AWS S3.
).Сегодня я столкнулся с проблемой. Когда я пытаюсь получить медиа файл с AWS S3, Django корректно скачивает его с удаленного ведра, сохраняет в дир /tmp/
, получает корректные метаданные ответа, но сам ответ не работает: он вызывает бесконечное состояние "in progress" ответа на стороне фронтенда (пробовал с Postman и Swagger). "В процессе" означает "фронтенд-приложение ждет, пока ответ будет получен", но на стороне бэкенда нет бесконечного цикла. Django может предоставить следующие ответы, даже если я использую тестовый сервер dev (это означает, что никакие рабочие не блокируются, потому что тестовый сервер django имеет только одного рабочего).
Информация о запросе и ответе (Django Silk):
Есть часть моего представления, которая обеспечивает загрузку изображения:
from django.http import Http404, StreamingHttpResponse
from wsgiref.util import FileWrapper
class ImageDetailAPIView(DetailDownloadAPIView):
queryset = Image.objects.filter(is_soft_deleted=False)\
.prefetch_related('thumbnails')
serializer_class = ImageSerializer
@swagger_auto_schema(responses=image_detail_responses)
def get(self, request, *args, **kwargs):
try:
instance = self.get_object()
except Http404:
raise FileNotFoundException
service = ImageDownloadService(instance)
chunk_size = 8192
file_path, status_code = service.download()
if status_code == 200:
response = StreamingHttpResponse(
FileWrapper(open(file_path, 'rb'), chunk_size),
content_type=instance.mime_type
)
response['Content-Length'] = instance.size
response['Content-Disposition'] = "attachment; filename=%s" % instance.file_name
return response
raise UnexpectedCaseException(is_for_file=True)
Архитектура и код сервиса не важны, так как я уже обнаружил, что он работает правильно: образ правильно идентифицировать в AWS и далее загрузить в /tmp/downloaded-file.webp
. Замена StreamingHttpResponse
на FileResponse
не работает. Я тестировал все это с изображениями с форматами .png
и .webp
, и это все равно не работает.
Я решил проблему, используя этот пост (но не нашел причины ее возникновения):
- добавьте
django.middleware.gzip.GZipMiddleware
промежуточное ПО в переменную настроек проектаMIDDLEWARE
. - напишите подкласс для моего существующего FileWrapper (код ниже).
FixedFileWrapper:
class FixedFileWrapper(FileWrapper):
def __iter__(self):
self.filelike.seek(0)
return self
Возможно, кто-то может объяснить мне причину моей проблемы?