2015-05-01 14 views
5

Mam sytuację, która mnie zaskoczyła, więc szukam pomocy, którą mogę uzyskać.Laravel 5 Odpowiedź HTTP, pliki M4V i iOS MPMoviePlayerViewController

Mam aplikację na iOS, która używa MPMoviePlayerViewController do odtwarzania plików wideo M4V zarządzanych przez stronę Laravel 5.

Pliki wideo odtwarzane są doskonale w porządku (na iOS), jeśli są pobierane bezpośrednio z folderu Laravel 5/public. Jednak zazwyczaj przechowuję i serwuję pliki wideo z Laravel 5's Storage Facade, ponieważ zamierzam użyć S3 i elastycznego transkodera.

Działa to w FireFox z wtyczką przeglądarki QuickTime, VLC i innymi klientami przesyłania strumieniowego wideo, ale nie z naszą aplikacją na iOS.

O ile mogę powiedzieć, MPMoviePlayerViewController jest wybredny o tym, jak formatowana jest odpowiedź HTTP. Próbowałem StreamedResponse, ale to nie pomaga.

Tak na przykład następujący adres URL, który ściąga plik bezpośrednio z katalogu/public współpracuje z iOS:

http://172.16.160.1/video_ae9a7da0efa211e4b115f73708c37d67.m4v 

Ale jeśli mogę użyć laravel 5 wyciągnąć plik z magazynu z tego adresu URL iOS nie będzie Graj.

http://172.16.160.1/api/getfile/f444b190ef5411e4b7068d1890d109e8/video_ae9a7da0efa211e4b115f73708c37d67.m4v 

Note iOS nie przewiduje żadnych znaczących błędów, aby pomóc debugowania to, ale jestem pewien, w jaki sposób jej moja odpowiedź HTTP jest dokonywana przez laravel 5.

Oto moja Droga:

Route::get('myapi/getfile/{filename?}', '[email protected]')->where('filename', '(.*)'); 

Oto moja Kontroler:

public function getfile($filename) 
{ 
    return $api = API::getfile($filename); 
} 

Oto moja model:

public static function getfile($filename) { 
$file = Storage::disk('local')->get('Files/'.$filename); 
return (new Response($file, 200))->header('Content-Type', 'video/mp4'); 
} 

Jeśli pominięto jakiekolwiek dodatkowe informacje, proszę dać mi znać, a ja to zrobię. Moim następnym krokiem może być ustawienie testowego Wiresharka i zobaczenie, jak wygląda uścisk dłoni.

Z góry dziękujemy za pomoc. :-)

Odpowiedz

4

Wygląda na to, że mam odpowiedź na własne pytanie. Podstawową przyczyną było to, że Laravel 5 nie obsługuje natywnych żądań HTTP podczas przesyłania plików.

Ten post znajduje się tutaj dostał mnie na właściwe tory:

MPMoviePlayerPlaybackDidFinishNotification is called immediately

I wtedy okazało dwa posty na robienie tego laravel 5:

http://laravel.io/forum/09-23-2014-how-to-support-http-byte-serving-in-file-streams

https://gist.github.com/m4tthumphrey/b0369c7bd5e2c795f6d5

cofam tylko to, że nie mogę korzystać z Frontu do bezpośredniego dostępu do f jako strumienie. To rozwiązanie może być używane tylko dla plików zlokalizowanych w lokalnym systemie plików.

public static function getfile($filename) { 

$size = Storage::disk('local')->size('files/'.$filename); 
$file = Storage::disk('local')->get('files/'.$filename); 
$stream = fopen($storage_home_dir.'files/'.$filename, "r"); 

$type = 'video/mp4'; 
$start = 0; 
$length = $size; 
$status = 200; 

$headers = ['Content-Type' => $type, '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); 
} 

return Response::stream(function() use ($stream, $start, $length) { 
    fseek($stream, $start, SEEK_SET); 
    echo fread($stream, $length); 
    fclose($stream); 
    }, $status, $headers); 
} 
+0

dzięki za ten udział, być może nagłówki powinny zostać rozszerzone o "Content-Transfer-Encoding" => "binarny", "Content-Disposition" => "załącznik; filename = "'. $ filename." "' – simon

+0

Wielkie dzięki za to. Uratował mnie sporo czasu po tym, jak spędził ponad 2 godziny, próbując uzyskać wideo z iPhone'a wyświetlane w Safari (na pulpicie) z Laravel. – AndyDunn