在rails应用程序中处理大型文件上传的最佳方法是什么?

时间:2013-05-25 12:26:38

标签: ruby-on-rails http bittorrent large-file-upload

我有兴趣了解在Rails应用程序中处理大型文件上传的不同方法,2-5Gb文件。

据我所知,为了传输这样大小的文件,需要将其分解为更小的部分,我已经做了一些研究,这是我到目前为止所做的。

所有这些方法都可以像FTP一样恢复,我不想使用FTP的原因是我想保留在网络应用程序中,如果可能的话?我使用了carrierwave和paperclip,但是我正在寻找能够恢复的东西,因为上传一个5Gb的文件可能需要一些时间!

在我列出的这些方法中,我想了解哪些方法运作良好,以及是否有其他方法可能会丢失?如果可能的话,没有插件,宁愿不使用Java Applets或Flash。另一个问题是这些解决方案在上传时将文件保存在内存中,这也是我希望尽可能避免的约束。

6 个答案:

答案 0 :(得分:34)

我已经在几个网站上处理了这个问题,使用了上面介绍的一些技术和一些你没有说过的技术。好消息是允许大量上传实际上非常现实。

这很大程度上取决于您在上传文件后实际计划对文件做些什么...您需要对文件执行的工作越多,您就越想将它放到服务器上。如果您需要立即处理上传,您可能想要做一个纯粹的rails解决方案。如果您不需要进行任何处理,或者它不是时间关键的,您可以开始考虑“混合”解决方案......

信不信由你,我使用mod_porter实际上运气不错。 Mod_porter让apache做了一些你的应用通常会做的工作。它有助于在上传过程中不占用线程和一堆内存。它会在您的应用中生成一个本地文件,以便于处理。如果你注意处理上传文件的方式(思考流),你可以使整个过程使用非常少的内存,即使是传统上相当昂贵的操作。这种方法只需要很少的实际设置来使您的应用程序正常工作,并且不需要对代码进行真正的修改,但它确实需要特定的环境(apache服务器),以及配置它的能力。

我也很幸运使用jQuery-File-Upload,它支持像chunked和resumable uploads这样的好东西。如果没有类似mod_porter的东西,这仍然可以在上传过程中占用整个执行线程,但如果做得对,它在内存上应该是合适的。这也会导致文件“关闭”,因此易于处理。这种方法需要调整您的视图层才能实现,并且不适用于所有浏览器。

您提到了FTP和bittorrent作为可能的选项。这些并不像您想象的那样糟糕,因为您仍然可以将文件放在非常接近服务器的位置。它们甚至不是互斥的,这很好,因为(正如你所指出的)它们确实需要一个额外的客户端,可能会或可能不会出现在上传机器上。它的工作方式基本上就是为你设置一个可以转储的区域,你的应用程序可以看到它。然后,如果您需要进行任何处理,则运行一个cron作业(或其他)来监视该位置以进行上载并触发您的服务器处理方法。这并不能让您获得上述方法可以提供的即时响应,但您可以将间隔设置得足够小以使其非常接近。这种方法唯一真正的优点是所使用的协议更适合传输大文件,根据我的经验,额外的客户需求和分散的流程通常超过了它的任何好处。

如果您根本不需要任何处理,最好的选择可能就是直接与他们一起使用S3。这个解决方案落到你实际需要对除了将它们作为静态资产服务器之外的文件做任何事情的第二个....

我没有在rails应用程序中使用HTML5 FileSystemAPI的经验,所以我不能说到这一点,虽然它似乎会严重限制你能够支持的客户端。

不幸的是,没有一个真正的银弹 - 所有这些选项都需要在你想要完成的环境中与你的环境进行权衡。例如,您可能无法配置Web服务器或永久写入本地文件系统。对于它的价值,我认为jQuery-File-Upload可能是大多数环境中最好的选择,因为它只需要修改您的应用程序,因此您可以最轻松地将实现移动到另一个环境。

答案 1 :(得分:4)

这个项目是一个基于HTTP的新协议,支持大文件的可恢复上传。它通过提供自己的服务器来绕过Rails。

http://tus.io/

答案 2 :(得分:3)

http://www.jedi.be/blog/2009/04/10/rails-and-large-large-file-uploads-looking-at-the-alternatives/对选项进行了一些很好的比较,包括Rails以外的一些选项。

请仔细检查。我的情况很有帮助

另一个网站是: - http://bclennox.com/extremely-large-file-uploads-with-nginx-passenger-rails-and-jquery

如果其中任何一项无法解决,请告诉我

答案 3 :(得分:1)

我会绕过rails服务器并将大文件(拆分为块)直接从浏览器发布到Amazon Simple Storage。有关使用JavaScript拆分文件,请查看此post。我有点好奇这种设置的性能如何,我觉得这个周末我会修改这个设置。

答案 4 :(得分:1)

我认为Brad Werth确定了答案

只有一种方法可以直接上传到S3(即使你在理论上使用aws lambda来通知你的应用程序之后你确实需要一些重新处理......但说实话我只是在这里猜测,我是关于为了自己解决同样的问题,我稍后会对此进行扩展)

http://aws.amazon.com/articles/1434

如果您使用carrierwave

答案 5 :(得分:0)

让我也确定一些可能有助于其他人寻找现实世界解决方案的选项。

我有一个带有 Ruby 2.7 的 Rails 6,这个应用程序的主要目的是创建一个类似于 Google 驱动器的环境,用户可以在其中上传图像和视频,然后他们再次处理它们以获得高质量。

显然,我们确实尝试过使用 Sidekiq 后台作业使用本地处理,但在 1GB 或更多的大型上传过程中它是压倒性的。 我们确实尝试过 tuts.io,但我个人认为不像 Jquery 文件上传那样容易设置。

所以我们尝试了 AWS..按照下面列出的步骤移动,它就像一个魅力......

  • 使用 React 拖放区上传器...我们将多个文件上传到 S3。
  • 我们为输入存储桶设置了 Aws Lambda,以触发该存储桶上所有类型的对象创建。
  • 此 Lambda 会转换文件,并再次将重新处理的文件上传到另一个文件 - 输出存储桶,并使用 Aws SNS 通知我们以跟踪哪些有效和哪些失败。
  • 在 Rails 方面...我们只是动态地使用新的输出存储桶,然后使用 Aws Cloud-front 分发来提供它。

您可以查看 MediaConvert 上的 Aws 注释以查看分步指南,他们还有一个编写良好的 Github 存储库,可用于各种实验。

希望对这里的人有所帮助。