我正在开发一个ruby CGI视频处理工具,并希望在点击start-ffmpeg-for-an-hour-long-encoding-spree按钮后将用户重定向到另一个位置。
以下是代码:
@cgi.out("status" => "302", "location" => @job.report_url) {''}
@cgi.out{''}
@job.start
这样做适用于Safari 5.0.5。但Firefox在重定向之前等待脚本完成他的工作。而且,如果你的脚本需要比Apache超时更长的时间,那么它可能永远不会发生。
我希望得到一个cin.close()方法的kinf。哪个存在!但是CGI :: Session方法与我无关。
这是另一个类似的问题......但不是重复!因为我需要在重定向后使用stdin,stdout和stderr :Returning a response with Ruby CGI before script is finished?
那么,如何使用相同的脚本在 执行其他任务之前发送完整的CGI响应 ?
答案 0 :(得分:1)
解决此类问题的常用方法是将应用程序分成两个进程。
处理部分通常是等待来自众多cgi部分的消息的应用程序的单个实例。 cgi部分只是向处理部分提交请求。可以随意进行通信,但通常使用作业/消息队列完成。
这样,只要将作业提交到队列,您就可以重定向用户,处理部分最终将转发您的视频转码。
另一个优点是,一堆并发请求不会使您的计算机过载数十次并发转码操作。您还可以相对轻松地将处理部件移动到一台或多台机器上(取决于您选择的通信形式)/
快速web search将向您展示数十个示例。
答案 1 :(得分:1)
某些浏览器(如Firefox)在处理数据之前填充缓冲区。
在家庭测试中,我通过发送4096个空格来完成这个技巧:
@cgi.out("status" => "302", "location" => @job.report_url) { ' ' * 4096 }
@job.start
更新:以下是我的完整测试代码:
#!/usr/bin/ruby
require 'cgi'
# change the line below to test; e.g.: buf = ''
buf = ' ' * 4096
cgi = CGI.new
cgi.out('status' => '302', 'location' => 'http://www.example.com') { buf }
sleep 10
puts 'end'
显然,'end'
永远不会出现,因为浏览器之前已被重定向。
当buf
为空时,Firefox会在重定向之前等待10秒。当它“满”(即4K空格)时,浏览器会立即重定向。在Ubuntu 10.04中使用Firefox 4.0,在Windows 7中使用Firefox 4.0.1进行测试。
答案 2 :(得分:1)
尝试将Content-Length标头设置为0,而不是发送空缓冲区。 对于off请求处理,Kernel#fork应该有帮助。
经过一些测试。这是需要做的。 Content-Length由cgi.out正确设置。您只需传递一个空字符串将其设置为0。
另外,正如我在评论中所述,关闭stdout有效地关闭了连接服务器端。 我用lighttpd + ree,firefox和chrome测试了这段代码。
require 'cgi'
cgi = CGI.new
cgi.out('status' => '302', 'location' => 'http://www.google.com') { "" }
$stdout.close
# here we do a very very long task
sleep 30
exit 0
答案 3 :(得分:1)
好吧,终于明白了。
但它看起来更像是黑客而不是真正的解决方案:
@cgi.out("status" => "303", "Connection" => "close", "Content-Length" => 1, "Location" => @job.report_url) {' '}
@job.start
有两个关键因素可以使它发挥作用,两者都需要:
Content-Lenght
设置为大于0的值.1适用于一个内容空间。Connection
设为close
。这很尴尬,因为理论上这在HTTP 1.1 Keep Alive连接中可能完全正常。但这似乎触发了Firefox 4中的页面呈现。在作业提交的POST请求(HTTP 303)之后,我已切换到更正确的303 See Other
响应。但这没有任何效果,它对302响应也很有效。