目前,我只是提供这样的文件:
# view callable
def export(request):
response = Response(content_type='application/csv')
# use datetime in filename to avoid collisions
f = open('/temp/XML_Export_%s.xml' % datetime.now(), 'r')
# this is where I usually put stuff in the file
response.app_iter = f
response.headers['Content-Disposition'] = ("attachment; filename=Export.xml")
return response
Run Code Online (Sandbox Code Playgroud)
这个问题是我无法关闭,甚至更好地在返回响应后删除该文件.该文件被孤立.我可以想到一些关于这方面的hacky方法,但我希望有一个标准的方法在那里.任何帮助都是极好的.
Mic*_*kel 10
您不希望将文件指针设置为app_iter.这将导致WSGI服务器逐行读取文件(与之相同for line in file),这通常不是控制文件上载的最有效方式(想象每行一个字符).Pyramid支持的文件服务方式是通过pyramid.response.FileResponse.您可以通过传递文件对象来创建其中一个.
response = FileResponse('/some/path/to/a/file.txt')
response.headers['Content-Disposition'] = ...
Run Code Online (Sandbox Code Playgroud)
另一种选择是将文件指针传递给对象,app_iter但将其包装在pyramid.response.FileIter对象中,该对象将使用合理的块大小来避免只是逐行读取文件.
WSGI规范有严格的要求,即在响应结束时将调用包含close方法的响应迭代器.因此设置不应导致任何内存泄漏.双方并还支持方法,并因此将清理预期.response.app_iter = open(...)FileResponseFileIterclose
作为对这个答案的一个小更新,我想我会解释为什么FileResponse采用文件路径而不是文件指针.WSGI协议为服务器提供了一种可选功能,可以通过提供优化的机制来提供静态文件environ['wsgi.file_wrapper'].FileResponse如果您的WSGI服务器提供了该支持,它将自动处理此问题.考虑到这一点,您会发现将数据保存到ramdisk上的tmp文件并提供FileResponse完整路径,而不是尝试传递文件指针是一种胜利FileIter.
更新:
请参阅Michael Merickel的答案,以获得更好的解决方案和解释.
如果要在response返回文件后删除该文件,可以尝试以下操作:
import os
from datetime import datetime
from tempfile import NamedTemporaryFile
# view callable
def export(request):
response = Response(content_type='application/csv')
with NamedTemporaryFile(prefix='XML_Export_%s' % datetime.now(),
suffix='.xml', delete=True) as f:
# this is where I usually put stuff in the file
response = FileResponse(os.path.abspath(f.name))
response.headers['Content-Disposition'] = ("attachment; filename=Export.xml")
return response
Run Code Online (Sandbox Code Playgroud)
您可以考虑使用NamedTemporaryFile:
NamedTemporaryFile(prefix='XML_Export_%s' % datetime.now(), suffix='.xml', delete=True)
Run Code Online (Sandbox Code Playgroud)
进行设置,delete=True以便在文件关闭后立即将其删除.
现在,在with您的帮助下,您始终可以保证文件将被关闭,从而被删除:
from tempfile import NamedTemporaryFile
from datetime import datetime
# view callable
def export(request):
response = Response(content_type='application/csv')
with NamedTemporaryFile(prefix='XML_Export_%s' % datetime.now(),
suffix='.xml', delete=True) as f:
# this is where I usually put stuff in the file
response.app_iter = f
response.headers['Content-Disposition'] = ("attachment; filename=Export.xml")
return response
Run Code Online (Sandbox Code Playgroud)