如何在Heroku上传大文件(特别是视频)

时间:2012-07-18 05:39:48

标签: ruby-on-rails heroku upload http-error

我正在使用heroku来托管一个主要关注托管视频的网络应用程序。这些视频是通过vimeo pro托管的,我正在使用vimeo gem by matthooks来帮助处理上传过程。 上传适用于小文件,但不适用于较大的文件(例如~50mb)。

查看heroku日志显示我收到http错误413,表示“请求实体太大”。我相信这可能与heroku对文件上传的限制(大于30mb,according to this webpage)有关。但问题是,我在这个主题上找到的任何信息似乎都已过时且相互矛盾(如claims there is no size limit所示的此页面)。我也在heroku的网站上找不到任何关于此事的内容。

我搜索了谷歌并找到了一些有些相关的页面(onetwo),但没有适合我的解决方案。我发现的大多数页面都涉及将大文件上传到亚马逊s3,这与我正在尝试的不同。

以下是日志的相关输出:

2012-07-18T05:13:31+00:00 heroku[nginx]: 152.3.68.6 - - [18/Jul/2012:05:13:31 +0000]
  "POST /videos HTTP/1.1" 413 192 "http://neoteach.com/components/19" "Mozilla/5.0 
  (Macintosh; Intel Mac OS X 10.7; rv:13.0) Gecko/20100101 Firefox/13.0.1" neoteach.com

日志中没有其他错误。这是我尝试上传视频过大时出现的唯一输出。这意味着这不是超时错误或超过每个dyno分配的内存的问题。

heroku是否真的限制了上传大小?如果是这样,有没有办法改变这个限制?请注意,文件本身根本没有存储在heroku的服务器上,它们只是被传递给vimeo的服务器。

如果问题不限制上传大小,是否有人知道其他可能出错的地方?

非常感谢!

3 个答案:

答案 0 :(得分:4)

<强>更新

OP在这里。我仍然不确定为什么我得到这个特殊的413错误,但我能够提出一个使用s3_swf_upload gem工作的解决方案。实现涉及闪存,这不太理想,但它是我能够工作的唯一解决方案(我尝试过的3或4个)。

正如Neil指出的那样(感谢Neil!),我应该得到的错误是“H12 - 请求超时”。经过反复试验,我最终遇到了这个错误。当您尝试从控制器(使用Web dyno)将大文件上载到heroku服务器时会出现问题,因为服务器响应发布请求需要很长时间。

正确的方法是将文件直接发送到s3而不通过heroku。

以下是我的方法的高级概述:

  1. 使用s3_swf_upload gem向s3提供直接上传表单。
  2. 使用gem中提供的javascript回调函数检测文件上传时间。
  3. 使用javascript,发送一条帖子,让您的服务器知道该文件已上传完毕。
  4. 响应javascript帖子的控制器做了两件事:(a)为视频对象分配一个s3_key属性(在表单中作为参数提供)。 (b)使用delayed_job gem启动后台任务。
  5. 后台任务从s3中检索文件。我使用aws-sdk gem来完成此任务,因为它已经包含在s3_swf_upload中。 请注意,这与aws-s3 gem明显不同(实际上它们彼此冲突)。
  6. 从s3检索文件后,我使用vimeo gem将其上传到vimeo(仍然在后台)。
  7. 上面的实现有效,但不完美。对于大小接近500MB的文件,您仍然会在工作人员dynos中遇到R14错误。这是因为heroku每个dyno只分配512MB内存,所以你不能一次将整个文件加载到内存中。解决这个问题的方法是在最后一步中实现某种分块,从s3中检索文件并将其逐个上传到vimeo。我还在为这部分工作,我很乐意听到你的任何建议。

    希望这可能对某人有所帮助。有问题尽管问我。就像我说的那样,我的解决方案并不完美,所以如果你觉得它更好,可以自由添加你自己的答案。

答案 1 :(得分:2)

你最大的问题不是这里的文件大小,而是你希望用户将大文件上传到Heroku,然后传递它们。这里的问题是Heroku平台上的所有请求必须在30秒内返回第一个字节 - 在您的情况下这是非常不可能的。

因此,您需要考虑让用户直接上传到S3 / Vimeo / whereever,然后将您的应用程序数据连接到这些上传的资产。

如果你正在使用Ruby,那么载波直接宝石可能值得一看它是如何完成的。如果没有第三方服务,那么您可以通过一些代码进入页面,但这些代码会附加成本。

答案 2 :(得分:2)

我认为这里的最佳选择确实是直接上传到S3。它比允许用户将文件上传到您自己的服务器(或者在这种情况下是Heroku)更便宜,更安全。它也是许多视频托管平台使用的经过充分验证的模式(我知道vzaar会这样做)。

查看jQuery上传插件,该插件允许直接上传到S3:https://github.com/blueimp/jQuery-File-Upload

还可以查看围绕此主题的Railscast:#381和#383。