10

I am trying to stream a mp3 file to SoundManager with the HTTP/1.1 Partial Content header to allow some protection to my media files and also allow users to seek to different locations of the track. The code I have works in IE7-10, Firefox, Safari and Opera but refuses to work in Google Chrome. If I was to remove the Partial Content header it would play the file but wouldn't allow the user to seek.

When examining the network tab in Chrome's dev tools there are 2 requests, one is stuck with the status of pending and the other has the status of canceled. both of these requests have a size of 13B. The file I am trying to play is 9.11MB.

Below is the code I am using to set the headers and read the file.

        $name = $_GET['name'];
        $file_size = filesize($file);
        $file = "C:\xampp\htdocs\..\protected\music\testsong.mp3"; // song, user and all other checks are performed before this to get the file path.
        $etag = md5(uniqid(rand(), true));

        $open_file = fopen($file, 'rb');
        if( !$open_file ) throw new Exception('Could not open file');

        $start = 0;
        $end = $file_size - 1;

        if( isset($_SERVER['HTTP_RANGE']) && !empty($_SERVER['HTTP_RANGE']) ) {
            $range = explode('-', substr($_SERVER['HTTP_RANGE'], strlen('bytes=')));

            $start = $range[0];
            if( $range[1] > 0 ) $end = $range[1];

            header('HTTP/1.1 206 Partial Content');
            header('Status: 206');
            header('Accept-Ranges: bytes');
            header('Content-Range: ' . $_SERVER['HTTP_RANGE'] . '/' . $file_size);
            header('Content-Length: ' . ($end - $start + 1));
        } else header('Content-Length: ' . $file_size);

        header('Content-Type: ' . $content_type);
        if( $download ) header('Content-Disposition: attachment; filename="' . $name . '"');
        header('Last-Modified: ' . date('D, d M Y H:i:s \G\M\T', filemtime($file)));

        header('ETag: "' . $etag . '"');
        header('Expires: 0');
        header('Pragma: no-cache');
        header('Cache-Control: must-revalidate');

        if( $start > 0 ) fseek($open_file, $start);

        $bytes_position = $start;
        while( !feof($open_file) && $bytes_position <= $end ) {
            if( connection_aborted() || connection_status() != 0 ) throw New Exception('Connection Aborted');

            $chunk = 1048000;
            if( $bytes_position + $chunk > $end + 1 ) $chunk = $end - $bytes_position + 1;

            $chunk = fread($open_file, $chunk);
            if( !$chunk ) throw New Exception('Could not read file');

            print($chunk);
            flush();

            $bytes_position += $chunk;
        }

        fclose($open_file);
user2801323
  • 103
  • 1
  • 6
  • I'm having the same problem with MP4 streaming... http://stackoverflow.com/questions/25975943/php-serve-mp4-chrome-provisional-headers-are-shown-request-is-not-finished-ye. Did you solve urs by any chance? – Keo Strife Sep 22 '14 at 15:50
  • Check the bitrate of the files you are trying to stream. I had this same issue, but for me the requests completed just fine when I started to compress all of my audio files down to 128kbps. – arian1123 Aug 15 '16 at 18:59

1 Answers1

1

I'm pretty sure the problem you're having is with the content-range header

try this instead

header('Content-Range: bytes ' . $start . '-' . $end . '/' . $file_size);
Swayze
  • 191
  • 6