Rails byte-range request support

Hi,

I'm trying to serve the iPhone a video file from my controller using send_file. However, it appears as thought the iPhone requires byte- range request support and rails doesn't seem to support this.

If I give the iPhone a url that points to an actual file (i.e. it's served by my webserver nginx, instead of rails) it downloads and plays it fine.

Here is the proof (from the iphone docs):

This byte-range request should only return 100 bytes from the video:

curl --range 0-99 http://test.com/7_7.3g2 -o /dev/null   % Total % Received % Xferd Average Speed Time Time Time Current                                  Dload Upload Total Spent Left Speed   0 100 0 100 0 0 49 0 --:--:-- 0:00:02 --:--:-- 97

As you can see it does, i.e. byte-range support. Now lets try the same thing on my controller:

curl --range 0-50 http://test.com/play_video -o /dev/null   % Total % Received % Xferd Average Speed Time Time Time Current                                  Dload Upload Total Spent Left Speed 100 261k 100 261k 0 0 44310 0 0:00:06 0:00:06 --:--:-- 68172

As you can see it downloaded the entire file, i.e. no byte-range request.

Any idea how I can get around this issue, because I really need to be able to server the file via my controller.

Well you need to do 2 things: extract the desired range, for which I imagine you could get from poking around with the environment ActionController sets up for you. Secondly send_file would have to support sending a range of data, which it currently doesn't. However the source to send_file isn't complicated. It shouldn't be hard to add this.

Fred

A quick glance at the api shows this:

  • :filename - suggests a filename for the browser to use. Defaults to File.basename(path).
  • :type - specifies an HTTP content type. Defaults to ‘application/octet-stream’.
  • :disposition - specifies whether the file will be shown inline or downloaded. Valid values are ‘inline’ and ‘attachment’ (default).
  • :stream - whether to send the file to the user agent as it is read (true) or to read the entire file before sending (false). Defaults to true.
  • :buffer_size - specifies size (in bytes) of the buffer used to stream the file. Defaults to 4096.
  • :status - specifies the status code to send with the response. Defaults to ‘200 OK’.

What if you set :buffer_size => 100? Does that work?

The fix is to the X-Sendfile or X-Accel-Redirect for apache/ighthttp or nginx respectively.

Definitely... You don't want to do this in Rails because a) apache/lighttpd/nginx are tuned for this, b) mongrel buffers responses from rails, so this could eat up some memory, and c) longer responses can lock the mongrel process from responding to other rails requests.

What should I do?