我需要发送一个pdf文件和一些其他参数来响应使用django rest框架的get API调用。
我该怎么办?
我尝试了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 :(得分:11)
这里的问题是你试图返回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
另一种方法是使用base64 encoding之类的内容将PDF编码为文本。这将大大增加您的响应大小,但它将允许您毫无问题地使用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。
答案 1 :(得分:6)
如果您确实需要直接从后端提供二进制文件(例如,当它们动态生成时),您可以使用自定义renderer:
from rest_framework.renderers import BaseRenderer
class BinaryFileRenderer(BaseRenderer):
media_type = 'application/octet-stream'
format = None
charset = None
render_style = 'binary'
def render(self, data, media_type=None, renderer_context=None):
return data
然后在视图集中的操作中使用它:
@detail_route(methods=['get'], renderer_classes=(BinaryFileRenderer,))
def download(self, request, *args, **kwargs):
with open('/path/to/file.pdf', 'rb') as report:
return Response(
report.read(),
headers={'Content-Disposition': 'attachment; filename="file.pdf"'},
content_type='application/pdf')
答案 2 :(得分: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和stream)做出回应。
答案 3 :(得分:0)
您可以发送 pdf 文件作为对任何请求的响应,而无需安装任何软件包。
您可以执行以下操作。
def get(request, *args, **kwargs):
# some code
# some code
with fs.open("path/to/file/Report.pdf") as pdf:
response = HttpResponse(pdf, content_type='application/pdf')
filename = "Report.pdf"
response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
return response
现在,打开您的 postman
并点击 get/post
请求。
重要提示:在点击 postman 中的 send
按钮之前,选择选项 send and download
。