如何在Django中直接从urllib渲染PDF并实现下载,无需保存文件

0 投票
1 回答
648 浏览
提问于 2025-04-18 02:11

我以前总是把想要让用户下载的文件保存在django中。在我的项目里,我用的代码比如说:

def keyDownload(request, benutzername):
        benutzernameKey = benutzername +".key"
        fsock = open('/var/www/openvpn/examples/easy-rsa/2.0/keys/'+benutzernameKey, 'r')
        response = HttpResponse(fsock, mimetype='application/pgp-keys')
        response['Content-Disposition'] = "attachment; filename = %s " % (benutzernameKey)
        return response

我有一个pdf文件,是通过urllib获取的:

url = "http://www.urltomypdf.com"
sock = urllib2.urlopen(url)
with open('report.pdf', 'wb') as f:
    while True:
        content = sock.read()
        if not content: break
        f.write(content)

现在我把这个pdf文件保存为report.pdf。但是我的目标是直接把它显示在我的模板里,使用django中的一个函数。这可能吗?

1 个回答

2

在Django 1.5版本中,新增了一个叫做StreamingHttpResponse的类,可以用来根据一个迭代器来逐步发送响应。你的视图和迭代器可以像这样:

def stream_pdf(url, chunk_size=8192):
    sock = urllib2.urlopen(url)
    while True:
        content = sock.read(chunk_size)
        if not content: break
        yield content

def external_pdf_view(request, *args, **kwargs):
    url = <url> # specify the url here
    response = StreamingHttpResponse(stream_pdf(url), content_type="application/pdf")
    response['Content-Disposition'] = "filename='%s'" % <filename> #specify the filename here
    return response

在Django 1.5之前,你也可以通过将一个迭代器传给HttpResponse来逐步发送响应,但这样做有几个注意事项。首先,你需要在你的视图函数上使用@condition(etag_func=None)这个装饰器。其次,有些中间件可能会阻止正确的逐步响应,所以你需要绕过这些中间件。最后,只有当内容的长度达到1024字节时,才会发送一部分内容,所以chunk_size应该设置为超过1024。

撰写回答