我有以下视图代码,试图将zip文件“流”到客户端进行下载:
import os
import zipfile
import tempfile
from pyramid.response import FileIter
def zipper(request):
_temp_path = request.registry.settings['_temp']
tmpfile = tempfile.NamedTemporaryFile('w', dir=_temp_path, delete=True)
tmpfile_path = tmpfile.name
## creating zipfile and adding files
z = zipfile.ZipFile(tmpfile_path, "w")
z.write('somefile1.txt')
z.write('somefile2.txt')
z.close()
## renaming the zipfile
new_zip_path = _temp_path + '/somefilegroup.zip'
os.rename(tmpfile_path, new_zip_path)
## re-opening the zipfile with new name
z = zipfile.ZipFile(new_zip_path, 'r')
response = FileIter(z.fp)
return response
但是,这是我在浏览器中获得的响应:
Could not convert return value of the view callable function newsite.static.zipper into a response object. The value returned was .
我想我没有正确使用FileIter。
自Michael Merickel建议更新以来,FileIter功能正常运行。但是,仍然挥之不去的是客户端(浏览器)上出现的MIME类型错误:
Resource interpreted as Document but transferred with MIME type application/zip: "http://newsite.local:6543/zipper?data=%7B%22ids%22%3A%5B6%2C7%5D%7D"
为了更好地说明问题,我在Github上添加了一个小.py
和.pt
文件: https://github.com/thapar/zipper-fix
答案 0 :(得分:6)
FileIter
不是响应对象,就像您的错误消息所示。它是一个可以用于响应体的迭代,就是这样。此外,ZipFile
可以接受文件对象,这比文件路径更有用。让我们尝试写入tmpfile
,然后将该文件指针倒回到开头,并使用它写出来而不做任何花哨的重命名。
import os
import zipfile
import tempfile
from pyramid.response import FileIter
def zipper(request):
_temp_path = request.registry.settings['_temp']
fp = tempfile.NamedTemporaryFile('w+b', dir=_temp_path, delete=True)
## creating zipfile and adding files
z = zipfile.ZipFile(fp, "w")
z.write('somefile1.txt')
z.write('somefile2.txt')
z.close()
# rewind fp back to start of the file
fp.seek(0)
response = request.response
response.content_type = 'application/zip'
response.app_iter = FileIter(fp)
return response
我根据文档将NamedTemporaryFile
上的模式更改为'w+b'
,以允许将文件写入和进行读取。
答案 1 :(得分:0)
目前的Pyramid版本为此用例提供了2个便捷类 - FileResponse,FileIter。下面的代码段将提供静态文件。我运行了这段代码 - 下载的文件被命名为“download”,就像视图名称一样。要更改文件名,请设置Content-Disposition标头或查看pyramid.response.Response的参数。
from pyramid.response import FileResponse
@view_config(name="download")
def zipper(request):
path = 'path_to_file'
return FileResponse(path, request) #passing request is required
文档: http://docs.pylonsproject.org/projects/pyramid/en/latest/api/response.html#
提示:如果可能,从视图中提取Zip逻辑