Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Re^3: Serving video files in specific byte-ranges

by Corion (Pope)
on Aug 31, 2011 at 14:16 UTC ( #923437=note: print w/ replies, xml ) Need Help??


in reply to Re^2: Serving video files in specific byte-ranges
in thread Serving video files in specific byte-ranges

Have you tried seek together with the appropriate Content-Range headers in your response? What were the problems you encountered?

Also see Simple HTTP in under 100 lines, which supports Range: queries and responses.


Comment on Re^3: Serving video files in specific byte-ranges
Select or Download Code
Re^4: Serving video files in specific byte-ranges
by goofball (Acolyte) on Sep 06, 2011 at 19:29 UTC
    That's a helpful link - thanks! Although, that code uses an HTTP::Response object to pass back to the daemon. Any advice on printing out the response object when not using a daemon? The CPAN docs are entirely clear on this (HTTP::Response and HTTP::Message), and when I implement the print $response->decoded_content in the following code, I get an error of Can't decode ref content at /usr/local/lib/perl5/site_perl/5.8.9/HTTP/Message.pm line 294.
    use HTTP::Response; use IO::File; my $response = new HTTP::Response( 404,undef,undef,"404 - Not foun +d." ); $|=1; my $file = new IO::File "< $path"; if (defined $file) { $response->code( 200 ); binmode $file; my $size = -s $file; my ($startrange, $endrange) = (0,$size-1); if (defined $ENV{HTTP_RANGE} and $ENV{HTTP_RANGE} =~ /bytes\s* +=\s*(\d+)-(\d+)?/) { $response->code( 206 ); ($startrange,$endrange) = ($1,$2 || $endrange); }; $file->seek($startrange,0); $response->header(Content_Length => $endrange-$startrange); $response->header(Content_Range => "bytes $startrange-$endrang +e/$size"); $response->content( sub { sysread($file, my ($buf), 16*1024); # No error checking ?? +? return $buf; }); }; print $response->decoded_content;

    Another option I tried, just printing the HTTP headers and content to STDOUT, follows below. This prints the requested ranges using a Transfer-Encoding method of chunked, as described here: w3.org and here: Wiki. There are no server-side errors using this script, but the iPhone Safari client still shows a broken file.

    my @ranges; if($ENV{HTTP_RANGE} =~ s/^bytes=//i) { @ranges = split /,/, $ENV{HTTP_RANGE}; print "Transfer-Encoding: chunked\n"; warn "printing ranges @ranges\n"; } else { print "Content-length: $filesize\n\n"; } if(@ranges) { open my $fh, '<', $path; foreach $range (@ranges) { my($begin, $end) = split /-/, $range; print "Content_Range: bytes $begin-$end/$filesize\ +n\n"; my $whence = ($begin)? 0 : 2; my $position = ($begin)? $begin : 0 - $end; seek $fh, $position, $whence; if($end) { $range = ($begin)? $end - $begin : $end; my $chunk_header = sprintf("%x", $range); print "$chunk_header\r\n"; sysread $fh, $_ , $range; print "$_\r\n"; warn "printed range of $range bytes from $begi +n to $end\n"; } else { while(<$fh>) { print } } } close $fh; print "0\r\n"; } else { open(FILE, $path) or die; while(<FILE>) { print } close(FILE); }

      Looking at the source of HTTP::Message, it just does not want to decode the content delivered by a callback:

      ... $content_ref = $self->content_ref; die "Can't decode ref content" if ref($content_ref) ne "SCALAR"; ...

      Either you fix HTTP::Message or you try it with ->content() instead of ->decoded_content. Alternatively, look at Plack as your server framework - it should handle callback responses more gracefully than your approach.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://923437]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (8)
As of 2014-11-26 09:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My preferred Perl binaries come from:














    Results (165 votes), past polls