创建 zip 存档以供即时下载
在我正在开发的 Web 应用程序中,用户可以创建一个充满文件的文件夹的 zip 存档。 代码如下:
files = torrent[0].files
zipfile = z.ZipFile(zipname, 'w')
output = ""
for f in files:
zipfile.write(settings.PYRAT_TRANSMISSION_DOWNLOAD_DIR + "/" + f.name, f.name)
downloadurl = settings.PYRAT_DOWNLOAD_BASE_URL + "/" + settings.PYRAT_ARCHIVE_DIR + "/" + filename
output = "Download <a href=\"" + downloadurl + "\">" + torrent_name + "</a>"
return HttpResponse(output)
但这会带来令人讨厌的副作用,即下载 zip 存档时需要长时间等待(10 秒以上)。 可以跳过这个吗? 是否可以将存档直接发送给用户,而不是将其保存到文件中?
我确实相信 torrentflux 提供了我正在谈论的这个 excat 功能。 能够压缩 GB 的数据并在一秒钟内下载。
In a web app I am working on, the user can create a zip archive of a folder full of files. Here here's the code:
files = torrent[0].files
zipfile = z.ZipFile(zipname, 'w')
output = ""
for f in files:
zipfile.write(settings.PYRAT_TRANSMISSION_DOWNLOAD_DIR + "/" + f.name, f.name)
downloadurl = settings.PYRAT_DOWNLOAD_BASE_URL + "/" + settings.PYRAT_ARCHIVE_DIR + "/" + filename
output = "Download <a href=\"" + downloadurl + "\">" + torrent_name + "</a>"
return HttpResponse(output)
But this has the nasty side effect of a long wait (10+ seconds) while the zip archive is being downloaded. Is it possible to skip this? Instead of saving the archive to a file, is it possible to send it straight to the user?
I do beleive that torrentflux provides this excat feature I am talking about. Being able to zip GBs of data and download it within a second.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
检查这个在 Django 中提供动态生成的 ZIP 存档
Check this Serving dynamically generated ZIP archives in Django
正如 mandrake 所说,HttpResponse 的构造函数接受可迭代对象。
幸运的是,ZIP 格式可以一次性创建存档,中央目录记录位于文件的最末尾:
(图片来自维基百科)
幸运的是,
zipfile 确实不会执行任何搜索。
这是我想出的代码。 一些注意事项:
所以,这里是:
As mandrake says, constructor of HttpResponse accepts iterable objects.
Luckily, ZIP format is such that archive can be created in single pass, central directory record is located at the very end of file:
(Picture from Wikipedia)
And luckily,
zipfile
indeed doesn't do any seeks as long as you only add files.Here is the code I came up with. Some notes:
So, here goes:
这是一个简单的 Django 视图函数,它将(作为示例)压缩
/tmp
中的任何可读文件并返回 zip 文件。当然,只有当 zip 文件能够方便地装入内存时,这种方法才有效 - 如果不能,您将不得不使用磁盘文件(您试图避免这种情况)。 在这种情况下,您只需将
file = StringIO()
替换为file = open('/path/to/yourfiles.zip', 'wb')
并替换file.getvalue()
包含读取磁盘文件内容的代码。Here's a simple Django view function which zips up (as an example) any readable files in
/tmp
and returns the zip file.Of course this approach will only work if the zip files will conveniently fit into memory - if not, you'll have to use a disk file (which you're trying to avoid). In that case, you just replace the
file = StringIO()
withfile = open('/path/to/yourfiles.zip', 'wb')
and replace thefile.getvalue()
with code to read the contents of the disk file.您使用的 zip 库是否允许输出到流。 您可以直接流式传输给用户,而不是暂时写入 zip 文件然后流式传输给用户。
Does the zip library you are using allow for output to a stream. You could stream directly to the user instead of temporarily writing to a zip file THEN streaming to the user.
可以将迭代器传递给 HttpResponse 的构造函数 (参见文档)。 这将允许您创建一个自定义迭代器,根据请求生成数据。 不过,我认为这不适用于 zip(您必须在创建时发送部分 zip)。
我认为正确的方法是在单独的过程中离线创建文件。 然后,用户可以监视进度,然后在文件准备好时下载文件(可能通过使用上述迭代器方法)。 这与 YouTube 等网站在上传文件并等待其处理时使用的方式类似。
It is possible to pass an iterator to the constructor of a HttpResponse (see docs). That would allow you to create a custom iterator that generates data as it is being requested. However I don't think that will work with a zip (you would have to send partial zip as it is being created).
The proper way, I think, would be to create the files offline, in a separate process. The user could then monitor the progress and then download the file when its ready (possibly by using the iterator method described above). This would be similar what sites like youtube use when you upload a file and wait for it to be processed.