使用Django在Heroku上上传大文件到AWS S3 Bucket,避免30秒请求超时问题。

15

我有一个Django应用程序,允许用户上传视频。它托管在Heroku上,上传的文件存储在S3存储桶中。 由于Heroku 30秒请求超时,我使用JavaScript从Django应用程序获取预签名请求后直接将文件上传到S3。 有没有可能通过Django后端上传大文件而不使用JavaScript并且不会影响用户体验?


我认为这篇文章涵盖了您的需求,并且适用于非Heroku环境。 https://devcenter.heroku.com/articles/s3-upload-python - wololoooo
你是否正在使用AWS SDK for javascript?用户体验不应该受到影响,根据AWS SDK for javascript创建相册的文档,前端看起来是完全可定制的。唯一的区别是上传视频与照片。此外,你为什么认为用户体验会受到影响?以上听起来是解决问题的最具成本效益、技术效率和正确的方式。 - benson
2个回答

6
您应该考虑以下几点来解决问题:
  • 为什么您的文件不应该先发送到django服务器,然后再发送到s3:将文件发送到django服务器,然后再发送到s3只是浪费计算能力和带宽。下一个问题是,为什么要将文件发送到django服务器,当您可以直接将它们发送到s3存储。
  • 如何上传文件到s3而不影响UX:将文件发送到django服务器肯定不是一个选项,因此您必须在前端处理此问题。但前端也有其自身的限制,如内存有限。如果文件很大,则无法处理,因为所有内容都会加载到RAM中,如果是非常大的文件,则浏览器最终会耗尽内存。我建议您使用类似于dropzone.js的工具。它不能解决内存问题,但确实可以为用户提供良好的UX,例如显示进度条、文件数量等。

从浏览器上传存在安全风险,不是吗?你最终会暴露秘钥和 API。 - omu_negru
当然可以,但是你必须在浏览器中使用临时凭证。这些凭证具有访问策略和过期时间,因此不会构成安全威胁。您可以在AWS S3文档中了解更多信息。 - Arpit Solanki
那么,“流式传输”文件行不行?我不熟悉AWS JS SDK,但是如果上传和S3处理程序都可以被视为套接字,那么它只需从一个套接字读取并写入另一个套接字,然后关闭两个套接字。 - omu_negru
套接字并不是唯一用于此的东西。在这个问题的背景下,你所说的“流式传输文件”是什么意思?由于它是一个文件,所以只能通过流式传输来发送,而不能将整个文件发送。 - Arpit Solanki
@omu_negru 只有 API 密钥被公开(这是可以的,因为它应该包含在所有请求中)。您将秘密密钥保留在 Django 应用程序/服务器上,并使用它生成临时签名 URL,浏览器使用该 URL。 - user

3
其他回答中的观点是正确的。简短回答“是否有任何方法可以在Django后端上传大文件而不使用JavaScript”这个问题的答案是“除非切换到Heroku之外,否则无法实现”。
请记住,传输到您的dynos的任何数据都会通过Heroku的路由网格进行,这是为了保护其有限资源而强制执行30秒请求限制。任何长时间运行的事务都会消耗带宽/计算等资源,这些资源本应用于服务其他请求,因此Heroku应用该限制以帮助跨数千个dynos保持运行。上传文件时,首先会受到客户端到服务器的带宽限制。然后,在您的dynos和S3之间的带宽上进行限制,还要加上dyno实际执行的任何处理。
文件越大,传输数据超过30秒超时的可能性就越大,特别是对于不可靠网络上的客户端而言,步骤1尤其如此。从客户端到S3创建直接路径是一个合理的妥协方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接