可以在 Django 中为大型非本地文件流式传输 zip 吗?

kra*_*r65 1 python django streaming zip

我有一个用 Django 编写的代理,它接收对某些文件的请求。在决定是否允许用户查看文件后,代理从远程服务获取文件并将其提供给用户。还有更多内容,但这是要点。

此设置适用于单个文件,但有一个新要求,即用户希望将多个文件作为 zip 文件一起下载。这些文件有时很小,但也可能变得非常大(100MB 以上),并且可以同时包含 2 到 1000 个文件。这可能会变得非常大,并且首先获取所有这些文件,压缩它们然后在同一个请求中为它们提供服务是一种负担。

我读到了创建“流式压缩”的可能性;一种打开 zip 文件的方法,然后开始发送该 zip 文件中的文件,直到您关闭它。我找到了几个 php 示例,并在 Python 中找到了django-zip-stream 扩展。它们都假设本地存储文件,django 扩展也假设 nginx 的用法。

在我的情况下,我想知道一些事情:

  1. 我没有本地存储的文件。我可以使用 async/await 结构获取它们并同时为它们提供服务。这意味着我的内存中总是有两个文件(我当前正在使用的一个文件,以及我从源服务器获取的下一个文件)。
  2. 不幸的是,我无法控制将提供此服务的 Web 服务器。我当然可以在它前面放一个 nginx 容器,但我不认为 nginx 可以从我存储在 Python 变量中的文件中提供服务,因为我从源服务器获取它们。
  3. 无论我是在 Python 中执行此操作还是让它在 nginx 中进行压缩,我认为所需的 CPU 周期将是巨大的。

有谁知道在我设置非常大的远程文件时流式传输 zip 是否是一个好主意?我有点担心由于 CPU 或内存限制,许多请求很容易对我们的服务器进行 DOS 处理。

我还可以构建一个队列来压缩文件并向用户发送电子邮件,但如果可能的话,我希望尽可能使应用程序保持无状态。

欢迎所有提示!

Mar*_*ndi 5

这对我来说听起来像是一个完美的用例,可以解决排队作业并在后台处理它们。

好处:

  1. 由于检索和压缩文件需要可变(并且可能很重要)的时间,因此应将其与 HTTP 请求/响应周期分离;
  2. 多个作业将被序列化以在任务队列中执行。

第二个优点是特别可取的,因为您已准备好接收多个并发请求。

我还会考虑使用带有 FileField 的“任务”Django 模型作为生成的 zip 文件的容器,因此 Nginx 将从媒体文件夹中静态有效地提供它。作为额外的好处,您将直接从 Django 管理用户界面监控正在发生的事情。

我在许多 Django 项目中使用过类似的方法,事实证明它非常健壮和易于管理;您可能想快速浏览一下我正在使用的以下 django 应用程序:https : //github.com/morlandi/django-task

总结一下:

  • 编写一个带有 FileField 的“任务”模型,用作压缩结果的容器
  • 收到请求后,在“task”表中插入一条新记录,并在后台队列中插入一条新作业
  • 后台作业负责收集资源并进行压缩;这是常见的 Python 东西
  • 完成后,将结果保存在 FileField 中并向用户发送通知
  • 用户将按照收到的 url 下载 zip 文件作为静态文件