2015-05-25 2 views
5

Мне нужно отправить PDF-файл и некоторые другие параметры в ответ на вызов API-интерфейса get с использованием рамки django rest.Как использовать фреймворк django rest для отправки файла в ответ?

Как я могу это сделать? Я пробовал this, но это ошибка <django.http.HttpResponse object at 0x7f7d32ffafd0> is not JSON serializable.

@detail_route(methods=['get']) 
def fetch_report(self, request, *args, **kwargs): 
    short_report = open("somePdfFile", 'rb') 
    response = HttpResponse(FileWrapper(short_report), content_type='application/pdf') 
    return Response({'detail': 'this works', 
     'report': response}) 
+0

Вы не можете сделать это за один шаг. Либо ответ в формате PDF, либо ответ JSON. Вы можете кодировать содержимое pdf в строку JSON, но это будет (выполнимо, но) трудно заставить его сохранить на клиенте. Обычно такие вещи выполняются в двухэтапном процессе: сначала получите ответ JSON, затем, если это удалось, запросите фактический файл. – spectras

ответ

2

Вы можете использовать проект DRF-PDF с PDFFileResponse:

from rest_framework import status 
from rest_framework.views import APIView 
from drf_pdf.response import PDFFileResponse 
from drf_pdf.renderer import PDFRenderer 


class PDFHandler(APIView): 

    renderer_classes = (PDFRenderer,) 

    def get(self, request): 
     return PDFFileResponse(
      file_path='/path/to/file.pdf', 
      status=status.HTTP_200_OK 
     ) 

Но, может быть, вы не можете ответить в обоих форматах (JSON и поток).

7

Проблема в том, что вы пытаетесь вернуть смесь JSON и PDF, которая либо не является тем, что вы ищете, либо собирается вернуть гигантский base64-кодированный ответ. PDF - это двоичный формат, а JSON - текстовый формат, и вы не можете их хорошо смешивать.

В представлении DRF вы можете напрямую вернуть ответ Django, который вы уже создаете (HttpResponse), и DRF передаст его и пропустит средства визуализации. Это полезно в таких случаях, поскольку это позволяет вам возвращать двоичный ответ, такой как изображение или PDF, не беспокоясь о том, что слой рендеринга DRF вызывает проблемы.

@detail_route(methods=['get']) 
def fetch_report(self, request, *args, **kwargs): 
    short_report = open("somePdfFile", 'rb') 
    response = HttpResponse(FileWrapper(short_report), content_type='application/pdf') 
    return response 

Альтернативой для кодирования PDF в виде текста, используя что-то вроде base64 encoding. Это значительно увеличит ваши размеры ответов, но это позволит вам без проблем использовать слой рендеринга DRF.

@detail_route(methods=['get']) 
def fetch_report(self, request, *args, **kwargs): 
    import base64 
    short_report = open("somePdfFile", 'rb') 
    report_encoded = base64.b64encode(short_report.read()) 
    return Response({'detail': 'this works', 
     'report': report_encoded}) 

Но маршрут я бы рекомендовал здесь, чтобы сгенерировать PDF и сохранить его в любом вашем хранилище медиа, или альтернативного частном месте, а также обеспечить прямую ссылку на него в своем ответе. Таким образом, вам не нужно беспокоиться о проблемах с кодировкой, не нужно напрямую возвращать PDF-файл, и вам не нужно беспокоиться о прямом обслуживании PDF-файла.

Смежные вопросы