猿问

是否可以使用 StreamingHttpResponse 生成 PDF,因为对于大型数据集可以使用

我有一个大型数据集,我必须为其生成 CSV 和 PDF。对于 CSV,我使用本指南:https://docs.djangoproject.com/en/3.1/howto/outputting-csv/

import csv


from django.http import StreamingHttpResponse


class Echo:

    """An object that implements just the write method of the file-like

    interface.

    """

    def write(self, value):

        """Write the value by returning it, instead of storing in a buffer."""

        return value


def some_streaming_csv_view(request):

    """A view that streams a large CSV file."""

    # Generate a sequence of rows. The range is based on the maximum number of

    # rows that can be handled by a single sheet in most spreadsheet

    # applications.

    rows = (["Row {}".format(idx), str(idx)] for idx in range(65536))

    pseudo_buffer = Echo()

    writer = csv.writer(pseudo_buffer)

    response = StreamingHttpResponse((writer.writerow(row) for row in rows),

                                     content_type="text/csv")

    response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'

    return response

它很好用。但是,我找不到任何可以为 PDF 做的事情。它可以?我使用render_to_pdf以及使用 PDF 模板。


慕妹3242003
浏览 177回答 4
4回答

手掌心

将 CSV 视为水果沙拉。你可以在一个大锅里把香蕉切成薄片,加入一些葡萄柚、一些菠萝……然后把整体分成单独的部分,然后放在一起放在桌子上(这是:你生成你的 CSV 文件,然后将它发送到客户端)。但是你也可以直接做单独的部分:在一个小碗里切一些香蕉片,加入一些葡萄柚,一些菠萝,......把这个小碗带到桌子上,然后对其他单独的部分重复这个过程(这是:您生成 CSV 文件并在生成它时将其部分发送给客户端)。好吧,如果 CSV 是水果沙拉,那么 PDF 就是蛋糕。您必须混合所有成分并将其放入烤箱。这意味着在烘烤整个蛋糕之前,您不能将一块蛋糕带到餐桌上。同样,在完全生成 PDF 文件之前,您无法开始将其发送给客户。所以,为了回答你的问题,这个 ( response = StreamingHttpResponse((writer.writerow(row) for row in rows), content_type="text/csv")) 不能为 PDF 完成。但是,一旦生成文件,您就可以使用其他答案中提到的方式将其流式传输到客户端FileResponse。如果您的问题是生成 PDF 花费的时间太长(例如可能会触发超时错误),请考虑以下几点:尝试优化生成算法的速度在客户端请求之前在后台生成文件并将其存储在您的存储系统中。您可能希望使用 cronjob 或celery来触发 PDF 的生成而不阻止 HTTP 请求。一旦准备好下载,就使用 websockets 将文件发送到客户端(参见django-channels)

暮色呼如

您尝试过FileResponse吗?像这样的东西应该可以工作,它基本上是你可以在Django 文档中找到的:import iofrom django.http import FileResponsefrom reportlab.pdfgen import canvasdef stream_pdf(request):    buffer = io.BytesIO()    p = canvas.Canvas(buffer)    p.drawString(10, 10, "Hello world.")    p.showPage()    p.save()    buffer.seek(io.SEEK_SET)    return FileResponse(buffer, as_attachment=True, filename='helloworld.pdf')

蝴蝶刀刀

查看您提供的链接,它确实提供了指向使用reportlab动态创建和发送 pdf 文件的页面的链接。import iofrom django.http import FileResponsefrom reportlab.pdfgen import canvasdef some_view(request):    # Create a file-like buffer to receive PDF data.    buffer = io.BytesIO()    # Create the PDF object, using the buffer as its "file."    p = canvas.Canvas(buffer)    # Draw things on the PDF. Here's where the PDF generation happens.    # See the ReportLab documentation for the full list of functionality.    p.drawString(100, 100, "Hello world.")    # Close the PDF object cleanly, and we're done.    p.showPage()    p.save()    # FileResponse sets the Content-Disposition header so that browsers    # present the option to save the file.    buffer.seek(0)    return FileResponse(buffer, as_attachment=True, filename='hello.pdf')

慕沐林林

我有一个类似的情况,我能够“生成和流式下载”文件csv,json和类型,我想对Excel -xml文件做同样的事情。xlsx不幸的是,我不能那样做。但是,那段时间我发现了一些事情文件、CSV、JSON 和 XML 是具有适当表示的文本文件。但是,对于 PDF 或 Excel(或类似文件),这些文件是使用适当的格式和适当的元数据构建的。只有当我们调用一些特定的方法时, PDF 和类似文档的二进制数据才会写入io 缓冲区。[showPage()和save()方法reportlab。(来源 - Django Doc)]如果我们检查文件流,PDF 和 Excel 需要复杂的特殊应用程序(例如:PDF 阅读器、Bowsers 等)来查看/读取数据,而对于 CSV 和 JSON,我们只需要一个简单的文本编辑器。因此,我得出结论,“通过流下载即时生成文件” (不确定我应该使用的正确技术术语是什么)的过程对于所有文件类型都是不可能的,但只适用于一些面向文本的文件注意:这是我有限的经验,可能有误。
随时随地看视频慕课网APP

相关分类

Python
我要回答