Ситуация:
- Я могу вернуть HTTP-ответ, содержащий файл.
- Я могу вернуть HTTP-ответ, содержащий хэш файла.
- Я не могу вернуть файл и хэш одновременно.
При попытке получить доступ к свойству streaming_content
объекта Django FileResponse, HTTP-запрос истекает ине может вернуться.
Этот код правильно возвращает запрошенный файл.
class DownloadFile(APIView):
permission_classes = (IsAuthenticated,)
def post(self, request):
try:
user = request.user
most_recent_report = Reports.objects.filter(user_id=user).latest("created_date")
most_recent_report_filepath = settings.BASE_DIR + most_recent_report.filepath
filename = 'report.pbf'
response = FileResponse(request, open(most_recent_report_filepath, 'rb'), content_type='application/json')
response['content-disposition'] = 'attachment; filename="%s"' % filename
return response
except Exception as e:
return Response({'status': str(e)}, content_type="application/json")
Этот код правильно возвращает хэш SHA256 запрошенного файла.
class DownloadFile(APIView):
permission_classes = (IsAuthenticated,)
def post(self, request):
try:
user = request.user
most_recent_report = Reports.objects.filter(user_id=user).latest("created_date")
most_recent_report_filepath = settings.BASE_DIR + most_recent_report.filepath
filename = 'report.pbf'
response = FileResponse(request, open(most_recent_report_filepath, 'rb'), content_type='application/json')
response['content-disposition'] = 'attachment; filename="%s"' % filename
h = hashlib.sha256()
partial_data = b''.join(response.streaming_content)
h.update(partial_data)
partial_hash = h.hexdigest()
return Response({'status': str(partial_hash)})
except Exception as e:
return Response({'status': str(e)}, content_type="application/json")
Этот код не может ничего вернуть, и время ожидания истекло.
class DownloadFile(APIView):
permission_classes = (IsAuthenticated,)
def post(self, request):
try:
user = request.user
most_recent_report = Reports.objects.filter(user_id=user).latest("created_date")
most_recent_report_filepath = settings.BASE_DIR + most_recent_report.filepath
filename = 'report.pbf'
response = FileResponse(request, open(most_recent_report_filepath, 'rb'), content_type='application/json')
response['content-disposition'] = 'attachment; filename="%s"' % filename
h = hashlib.sha256()
partial_data = b''.join(response.streaming_content)
h.update(partial_data)
partial_hash = h.hexdigest()
response['version'] = str(partial_hash)
return response
except Exception as e:
return Response({'status': str(e)}, content_type="application/json")
Есть ли какой-то способ обойти и файл, и доступ к streaming_content
в то же время?
РЕДАКТИРОВАТЬ:
Одним из возможных решений, которые я придумал, было создание двух объектов FileResponse. С первым объектом я могу получить доступ к streaming_content
и вычислить хэш файлов. Со вторым объектом я могу прикрепить хеш и вернуть объект. Это решение не очень хорошее, так как мне нужно загрузить файл дважды. Для больших файлов это ужасно неэффективно. Любые предложения приветствуются.
class DownloadFile(APIView):
permission_classes = (IsAuthenticated,)
def post(self, request):
try:
user = request.user
most_recent_report = Reports.objects.filter(user_id=user).latest("created_date")
most_recent_report_filepath = settings.BASE_DIR + most_recent_report.filepath
filename = 'report.pbf'
response1 = FileResponse(request, open(most_recent_report_filepath, 'rb'), content_type='application/json')
h = hashlib.sha256()
partial_data = b''.join(response1.streaming_content)
h.update(partial_data)
partial_hash = h.hexdigest()
response2 = FileResponse(request, open(most_recent_report_filepath, 'rb'), content_type='application/json')
response2['content-disposition'] = 'attachment; filename="%s"' % filename
response2['version'] = str(partial_hash)
return response2
except Exception as e:
return Response({'status': str(e)}, content_type="application/json")