Dav*_*vid 6 python pdf flask python-2.7
在有人说这是重复之前,我认为这不是因为我看过类似的问题而他们没有帮助我!
我在python中创建一个Flask服务器,我需要能够有一个显示pdf的url.
我试着使用以下代码:
@app.route('/pdf')
def pdfStuff():
with open('pdffile.pdf', 'rb') as static_file:
return send_file(static_file, attachment_filename='pdffile.pdf')
Run Code Online (Sandbox Code Playgroud)
这应该是这样的,当我去/pdf它时将显示pdf文件pdffile.pdf.
但是,这不起作用,因为当我运行代码时,我收到此错误:
ValueError: I/O operation on closed file
Run Code Online (Sandbox Code Playgroud)
情况怎么样?我的return语句在with语句中,因此不应该打开文件?
我试图用正常static_file = open(...)和使用try,并finally声明,如下所示:
static_file = open('pdffile.pdf','rb')
try:
return send_file(static_file, attachment_filename='pdffile.pdf')
finally:
static_file.close()
Run Code Online (Sandbox Code Playgroud)
上面的代码发生了同样的错误,我不明白为什么.有谁知道我做错了什么?
对不起,如果我是愚蠢的,有一些简单的我犯了错误!
非常感谢你提前!!
send_file与文件名一起使用,它将以您期望的方式打开、提供和关闭它。
@app.route('/pdf')
def pdfStuff():
return send_file('pdffile.pdf')
Run Code Online (Sandbox Code Playgroud)
尽管@iurisilvio 的答案解决了这个特定问题,但在任何其他情况下都不是有用的答案。我自己也在为此苦苦挣扎。
以下所有示例都抛出异常,ValueError: I/O operation on closed file.但为什么呢?
@app.route('/pdf')
def pdfStuff():
with open('pdffile.pdf', 'rb') as static_file:
return send_file(static_file, attachment_filename='pdffile.pdf')
@app.route('/pdf')
def pdfStuff():
static_file = open('pdffile.pdf','rb')
try:
return send_file(static_file, attachment_filename='pdffile.pdf')
finally:
static_file.close()
Run Code Online (Sandbox Code Playgroud)
我正在做一些稍微不同的事情。像这样:
@page.route('/file', methods=['GET'])
def build_csv():
# ... some query ...
ENCODING = 'utf-8'
bi = io.BytesIO()
tw = io.TextIOWrapper(bi, encoding=ENCODING)
c = csv.writer(tw)
c.writerow(['col_1', 'col_2'])
c.writerow(['1', '2'])
bi.seek(0)
return send_file(bi,
as_attachment=True,
attachment_filename='file.csv',
mimetype="Content-Type: text/html; charset={0}".format(ENCODING)
)
Run Code Online (Sandbox Code Playgroud)
对于前两种情况,答案很简单:
你给 一个流send_file,这个函数不会立即传输文件,而是包装流并将其返回给 Flask 以供将来处理。pdfStuff在 Flask 开始处理你的流之前,你的函数将准备好返回,并且在这两种情况下(with和),流将在你的函数返回之前finally关闭。
第三种情况更棘手(但这个答案为我指明了正确的方向:Why is TextIOWrapper close the给定的 BytesIO stream?)。以与上述相同的方式,bi仅在返回后进行处理build_csv。因此tw已经被抛弃给垃圾收集器了。当收集器销毁它时,tw将隐式关闭bi。这个问题的解决方案是tw.detach()在返回之前(这将停止TextIOWrapper影响流)。
旁注(如果我错了,请纠正我):这种行为是有限的,除非send_file提供类似文件的对象时,它会自行处理关闭。从文档( https://flask.palletsprojects.com/en/0.12.x/ api/#flask.send_file)中尚不清楚是否处理了关闭。我认为是这样的(.close()源代码中存在一些+也已实现的send_file用途),在这种情况下,您的方法可以更正为:werkzeug.wsgi.FileWrapper.close()
@app.route('/pdf')
def pdfStuff():
return send_file(open('pdffile.pdf','rb'), attachment_filename='pdffile.pdf')
Run Code Online (Sandbox Code Playgroud)
当然,在这种情况下,可以直接提供文件名。但在其他情况下,可能需要将文件流包装在某些操作管道中(解码/压缩)
| 归档时间: |
|
| 查看次数: |
1269 次 |
| 最近记录: |