2015-05-01 18 views
5

Tôi có một tình huống khiến tôi bối rối nên tôi đang tìm kiếm bất kỳ trợ giúp nào tôi có thể nhận được.Laravel 5 Phản hồi HTTP, Tệp M4V và iOS MPMoviePlayerViewController

Tôi có ứng dụng iOS sử dụng MPMoviePlayerViewController để phát tệp video M4V được quản lý bởi trang web Laravel 5.

Các tệp video phát hoàn toàn tốt (trong iOS) nếu chúng được tải trực tiếp từ thư mục công cộng 5 của Laravel. Tuy nhiên, tôi thường lưu trữ và phục vụ Video Files từ Mặt nạ lưu trữ của Laravel 5 vì cuối cùng tôi sẽ sử dụng S3 và trình chuyển mã đàn hồi.

Tính năng này hoạt động trong FireFox với plugin trình duyệt QuickTime, VLC và các ứng dụng phát video trực tuyến khác, chứ không phải ứng dụng iOS của chúng tôi.

Theo như tôi có thể nói MPMoviePlayerViewController đang được chọn lọc về cách Phản hồi HTTP đang được định dạng. Tôi đã thử StreamedResponse, nhưng điều đó dường như không giúp ích gì.

Vì vậy, ví dụ như các URL sau đó kéo các tập tin trực tiếp từ thư mục/công cộng hoạt động tốt từ iOS:

http://172.16.160.1/video_ae9a7da0efa211e4b115f73708c37d67.m4v 

Nhưng nếu tôi sử dụng Laravel 5 để kéo các tập tin từ lưu trữ với URL này iOS sẽ không chơi nó.

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

Note iOS không cung cấp bất kỳ lỗi nào có ý nghĩa, để giúp gỡ lỗi này, nhưng tôi tích cực của nó như thế nào đáp ứng HTTP của tôi đang được thực hiện bởi Laravel 5.

Đây là Route của tôi:

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

đây là điều khiển của tôi:

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

đây là mẫu của tôi:

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

Nếu tôi để lại bất kỳ thông tin hỗ trợ nào, vui lòng cho tôi biết và tôi sẽ đăng. Bước tiếp theo của tôi có thể là thiết lập Wireshark testbed và xem cái bắt tay trông như thế nào.

Cảm ơn bạn đã trợ giúp. :-)

Trả lời

4

Có vẻ như tôi có câu trả lời cho câu hỏi của riêng mình. Nguyên nhân cơ bản là Laravel 5 không hỗ trợ các yêu cầu phạm vi byte HTTP khi phục vụ các tệp.

bài này nằm đây đã cho tôi đi đúng hướng:

MPMoviePlayerPlaybackDidFinishNotification is called immediately

Sau đó tôi tìm thấy hai bài viết về việc này Laravel 5:

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

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

Các chỉ vẽ lại là tôi không thể sử dụng Mặt tiền lưu trữ để truy cập trực tiếp vào f ile như suối. Vì vậy, giải pháp này chỉ có thể được sử dụng cho các tệp nằm trên hệ thống tệp cục bộ.

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

cảm ơn chia sẻ này, có thể tiêu đề phải được mở rộng với 'Content-Transfer-Encoding' => 'binary', 'Content-Disposition' => 'attachment; filename = "'. $ filename.'" ' – simon

+0

Cảm ơn rất nhiều vì điều này. Đã lưu cho tôi một loạt thời gian sau khi đã dành hơn 2 giờ để cố gắng hiển thị video trên iPhone trong Safari (máy tính để bàn) từ Laravel. – AndyDunn

Các vấn đề liên quan