从内存中的 url 下载图像并在内存中创建 zip 存档以发送到浏览器
Posted
技术标签:
【中文标题】从内存中的 url 下载图像并在内存中创建 zip 存档以发送到浏览器【英文标题】:Downloading images from url in memory and creating zip archive in memory to send to the browser 【发布时间】:2012-04-19 19:47:21 【问题描述】:在我的 django 项目中,我需要发送一个 zip 文件到客户端进行下载。这个 zip 文件将包含从各种 url 下载的图像。
是否可以在不将图像文件写入磁盘的情况下将图像下载到内存中,然后将它们添加到内存中的 zip 文件中,再次不将 zip 文件写入磁盘,最后将 zip 文件发送到客户端进行下载?
我知道 urllib2 可用于图像下载和 zipfile 用于处理 zip 文件,但在内存中执行这些操作时会遇到问题。因此,非常感谢您提供一些示例。
谢谢
【问题讨论】:
【参考方案1】:使用 urllib2 下载文件。打开一个新的 ZipFile 进行写入(您需要一个 StringIO 对象)。将 url 的输出写入 ZilpFile.writestr。将 zip 文件附加到 django 响应。
import urllib2
from StringIO import StringIO
url = urllib2.urlopen('http://example.com/foo.jpg')
f = StringIO()
zip = zipfile.ZipFile(f, 'w')
zip.writestr('foo.jpg', url.read())
response = HttpResponse(f.getvalue(), content_type="application/zip")
response['Content-Disposition'] = 'attachment; filename=foobar.zip'
return response
【讨论】:
感谢您的回复。但在客户端,我没有将文件保存为对话框。我在 chrome 浏览器中尝试过。 服务器给你什么响应? 我检查了 chrome 调试器,在响应窗格中它显示了一些乱码。响应标头是 Connection:keep-alive Content-Disposition:attachment;文件名=foobar.zip 内容类型:application/zip 日期:星期四,2012 年 4 月 19 日 21:19:18 GMT P3p:CP="IDC CURa ADMa OUR IND PHY ONL COM STA" 服务器:gunicorn/0.14.2 传输编码:分块 我真的很抱歉,我是通过 ajax 发出请求的,我的错误:)。它的工作。非常感谢您的帮助!! :) 我在尝试此操作时遇到错误。也许是因为我从 s3 读取它,我得到了 url 用 urllib2 打开它。但是当我尝试使用 writestr() 时,我得到“TypeError: unicode argument expected, got 'str'”【参考方案2】:你可以这样做,很简单:
response = urllib2.urlopen('http://..')
img_bytes = response.read()
然后使用 ZipFile.writestr 将这些字节写入文件,在您之前创建的 Zip 中传递一个 StringIO 处理程序而不是一个真正的文件处理程序。完成写入文件后,将其作为 HTTPResponse 返回,设置适当的 mimetype 和内容处置。
但我不会为此使用 RAM。为什么不使用 tempfile.NamedTemporaryFile?
【讨论】:
我想不出有什么好的理由把它写到磁盘上,除非他正在压缩大量的图像,即使那样我也不确定这会不会有多大帮助。您所做的只是添加不必要的磁盘 io(这很可能是 Web 服务器上的限制因素) 下载操作取决于用户的并发性。如果他从各个链接即时抓取照片,则可能需要一些时间才能清除内存。来自 Django 文档:默认情况下,如果上传的文件小于 2.5 兆字节,Django 会将上传的全部内容保存在内存中。所以这取决于使用的大小和并发性,我猜。以上是关于从内存中的 url 下载图像并在内存中创建 zip 存档以发送到浏览器的主要内容,如果未能解决你的问题,请参考以下文章
使用 System.IO.Compression 在内存中创建 ZIP 存档