2

On our platform (based on Laravel 5.1) we provide audio and video content to registered users. The media files are stored outside the docroot of course.

So I use a method to provide the requested content. That works well on any browser and OS except Android (native or chrome). Android uses a byte range request for audio and video tags. The following code worked in the beginning and stopped working a while ago. I have no clue why. Any:

public function loadfile(Request $request, $type, $filename="")
{


    $filepath = $mediadirectory . $filename;

    if (File::isFile($filepath)) {
        $file = File::get($filepath);
        $mimetype = File::mimeType($filepath);
        $size = File::size($filepath);
        if ($mimetype=="audio/mpeg" || $mimetype=="video/mp4") {
            $stream = fopen($filepath, "r");
            $start = 0;
            $length = $size;
            $status = 200;

            $headers = ['Content-Type' => $mimetype, 'Content-Length' => $size, 'Accept-Ranges' => 'bytes'];

            if (false !== $range = $request->server('HTTP_RANGE', false)) {
                list($param, $range) = explode('=', $range);
                if (strtolower(trim($param)) !== 'bytes') {
                    header('HTTP/1.1 400 Invalid Request');
                    exit;
                }
                list($from, $to) = explode('-', $range);
                if ($from === '') {
                    $end = $size - 1;
                    $start = $end - intval($from);
                } elseif ($to === '') {
                    $start = intval($from);
                    $end = $size - 1;
                } else {
                    $start = intval($from);
                    $end = intval($to);
                }
                $length = $end - $start + 1;
                $status = 206;
                $headers['Content-Range'] = sprintf('bytes %d-%d/%d', $start, $end, $size);
                $headers['Connection'] = "keep-alive";
            }
            $response=new StreamedResponse(function() use ($stream, $start, $length) {
                fseek($stream, $start, SEEK_SET);
                echo fread($stream, $length);
                fclose($stream);
            }, $status, $headers);
            return $response->send();

        } else {
            return response($file, 200)->header('Content-Type', $mimetype)->header('Content-Length', $size)->header('Content-Disposition', 'filename="' . $filename . '"');
        }
    }

}

The html is straight forward html5:

<audio controls preload="auto">
    <source src="/loadfile/principiante.mp3" type="audio/mpeg">
</audio>
LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399

0 Answers0