【问题标题】:Uploading large files with Python/Django使用 Python/Django 上传大文件
【发布时间】:2011-11-23 21:03:36
【问题描述】:

我想知道通过使用 Django/Python 的网络应用程序上传大小约为 4GB 的文件是否有任何后果?我记得过去使用 Java 进行流式上传是首选方法,但今天仍然如此,还是使用 Django/Python 这样做完全安全?

【问题讨论】:

  • “绝对安全”?它一直是绝对安全的。什么可能是“不安全的”?你在担心什么?您想避免哪些问题?
  • Java 或类似的(作为浏览器插件——这部分是关键)过去曾用于此类事情,因为它可以解释启动、停止和恢复传输。通过 HTTP 上传 4GB 是疯狂的(只需使用标准文件上传字段)。期间。
  • 克里斯,为什么会发疯?你能提供更多细节吗?鉴于上传的文件与网络应用程序和用户帐户相关,因此 FTP 等不是解决方案,您能否提出替代方案。
  • 嗨@tdelam - 你在下面提到你有一个使用芹菜的解决方案。请问是否可以与我分享此解决方案?
  • @MichealJ.Roberts 当然,这是几年前的事了,但我会尽力记住。我创建了一个 celery 任务并使用 rabbit 来发送消息。当上传一个大文件时,我使用 celery 在后台对视频进行上传和编码。完成后,rabbit 会收到一条消息并发送上传完成的通知。我做了这样的事情:stackoverflow.com/questions/19231389/…

标签: python django


【解决方案1】:

对于未来的读者: 要在内存中存储 max filesize allowed,请在 settings.py 中设置以下内容:

FILE_UPLOAD_MAX_MEMORY_SIZE = 5242880 # make it 5Mb instead of 2Mb

当然,这对 4Gb 没有帮助。

【讨论】:

  • 是的,很容易确定。我最初的问题(几年前)更多地与上传超大文件的可能问题有关。我已经完成了那个应用程序。解决方案是使用 celery 和 rabbit mq 来排队上传。该应用程序已经运行了 8 年,可以完美地上传 100GB 视频文件并对其进行编码。
  • @tdelam 我也在尝试使用 celery 和 rabbit mq 上传文件。但我最多只能上传 2.5mb 的文件,因为超过该大小的 kombu 会给我错误 TypeError: cannot serialize '_io.BufferedRandom' object。你能帮帮我吗??
  • 嗨!你有没有机会解释一下你是如何解决这个问题的?我正在尝试做类似的事情,这真的很有帮助。
【解决方案2】:

默认情况下,如果上传的文件数据小于 2.5MB,Django 会将其放入内存中。任何更大的内容都将写入服务器的/tmp 目录,然后在传输完成时复制过来。 Django 的很多文件上传设置都可以自定义,详情请见the documentation。您还可以自定义文件处理,您肯定会想要这样做。

在我们考虑任何技术限制之前,使用浏览器上传如此大的文件会给用户带来非常糟糕的体验。没有关于传输进展情况的反馈(尽管谷歌浏览器确实以百分比显示上传状态),也无法暂停或恢复传输。

您也可能在服务器上遇到问题。除了每个线程处理流数据需要很长时间之外,您还有时间让系统将结果文件从/tmp 复制到正确的位置。

除非您非常有信心可以预见服务器在上传时可能遇到的任何问题,否则我建议这是一个坏主意。通过 google 很难找到这方面的任何信息,而且似乎确实有很多命中描述了大文件上传的问题。

虽然 Django 在技术上能够接收这么大的上传文件,但非常糟糕的用户体验和技术困难意味着这可能不是最好的方法。您是否考虑过使用专用软件来处理文件传输?

【讨论】:

  • 嗨,adamnfish,感谢您的彻底回复。我考虑过一项单独的服务,我唯一的问题是这是针对特定群体的特定网络应用程序,他们将上传他们创建的完整电影,可能是 ~4GB,所以我将限制设置为 4GB。这个想法是他们将能够上传这些文件,并将其绑定到他们的帐户。他们的帐户中可以有多个文件。我知道用户体验,他们也知道,他们对此很好,我只需要找出最好的方法来做到这一点,这样就不会有服务器问题
  • 使用django-chunked-uploads! (免责声明:我写了那个库)。
  • 嗨@juliomalegria,我看看你的图书馆。上传速度有多快?我还需要使用ftp 还是足够了?
【解决方案3】:

最后一个答案涵盖了它。我们通常上传 2.5mb+(但通常不是 4gb)

adamnish 链接是正确的,请参阅此 sn-p(来自他的 link to django docs)关于将文件写入磁盘,而不是先将其放入内存:

def handle_uploaded_file(f):
    with open('some/file/name.txt', 'wb+') as destination:
        for chunk in f.chunks():
            destination.write(chunk)

有关“块”呼叫的更多信息:https://docs.djangoproject.com/en/dev/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.chunks

页面包括如何设置“块”大小等。

【讨论】:

    猜你喜欢
    • 2011-11-28
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-12
    • 2011-03-18
    相关资源
    最近更新 更多