2010-03-01 28 views
9

Tôi có tình huống rất giống với người đã hỏi: Can I serve MP3 files with PHP? Về cơ bản tôi đang cố gắng bảo vệ tệp mp3 khỏi tải xuống trực tiếp, vì vậy người dùng phải thực hiện php để được xác thực trước. Dưới đây là mã của tôi:PHP Streaming MP3

header('Content-type: audio/mpeg'); 
header('Content-length: ' . filesize($file)); 
header('X-Pad: avoid browser bug'); 
Header('Cache-Control: no-cache'); 
header("Content-Transfer-Encoding: binary"); 
header("Content-Type: audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3"); 
readfile($file); 

Dưới đây là vấn đề của tôi: Các tập tin chỉ đóng một đoạn rất nhỏ của đầu (thông qua Quicktime trong trình duyệt) và sau đó dừng lại - Quicktime dường như nghĩ rằng chiều dài của tập tin duy nhất là miễn là đoạn nó quản lý để tải xuống. Khi tôi tải lại - nó phát một đoạn lớn hơn một chút - bất kể nó đã tải xuống đến thời điểm đó.

Đó có phải là vấn đề trong tiêu đề tôi đang gửi không? Tôi sẽ phát tệp như thế nào? Có vấn đề gì nếu một con swf đang đọc từ tập tin đó?

Cảm ơn!


Cảm ơn tất cả các bạn câu trả lời. Mặc dù không có thứ nào trong số này chính xác là những gì đã giải quyết được vấn đề, nhiều người trong số họ đã gửi cho tôi đúng hướng. Nhiều đánh giá cao. Đối với các giải pháp đầy đủ xem câu trả lời của tôi dưới đây

+0

Tôi đoán bạn không có lỗi đánh máy đó ("Tiêu đề") trong mã thực của bạn? Ngoài ra, bạn không cần hack X-Pad. Điều này chỉ cần thiết cho Netscape cổ xưa (xem http://george.hotelling.net/90percent/geekery/why_is_apache_sending_a_xpad_header.php). Bạn không cần Content-Transfer-Encoding, và bạn chỉ nên chỉ định Content-Type một lần (audio/mpeg là tốt). –

+0

@Matthew Flaschen: Các hàm PHP phân biệt chữ hoa chữ thường, do đó, nó chỉ là một vấn đề nhất quán. Content-Type có thể là vấn đề thực sự ở đây. – Piskvor

Trả lời

6

Đây là mẹo đã làm.

$dir = dirname($_SERVER['DOCUMENT_ROOT'])."/protected_content"; 
$filename = $_GET['file']; 
$file = $dir."/".$filename; 

$extension = "mp3"; 
$mime_type = "audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3"; 

if(file_exists($file)){ 
    header('Content-type: {$mime_type}'); 
    header('Content-length: ' . filesize($file)); 
    header('Content-Disposition: filename="' . $filename); 
    header('X-Pad: avoid browser bug'); 
    header('Cache-Control: no-cache'); 
    readfile($file); 
}else{ 
    header("HTTP/1.0 404 Not Found"); 
} 
+1

Bạn có thể muốn thực hiện một số xác nhận/vệ sinh trên $ _GET ['tệp'] trước khi đọc ... – Simon

+0

Tôi kiểm tra xem tệp có tồn tại 'if (file_exists ($ file)) {' ... Đó có phải là ý của bạn ? –

+4

Không, anh không có ý đó. Hãy suy nghĩ cho chính mình, điều gì xảy ra nếu ai đó cố gắng http://yoursite.com/yourscript.php?file=../../../home/someonesgirlfriend/secretdiary.doc – Jonny

1

nếu máy chủ của bạn đang chạy trên apache hoặc lighty, tôi sẽ đề nghị bạn nhìn vào x-sendfile

http://tn123.ath.cx/mod_xsendfile/

này cho phép bạn xử lý xác thực trong bạn ứng dụng php, nhưng hãy để máy chủ web của bạn xử lý việc truyền tệp. cải thiện hiệu suất bạn đạt được phải là một lợi ích bổ sung tốt đẹp

1

Bạn có thể thử HTTP chunking. Đặt tiêu đề "Chuyển mã hóa" thành "chunked", sau đó xuất kích thước của từng đoạn trước khi gửi. Kết thúc từng kích thước đoạn và đoạn bằng CRLF.

Đối với bất kỳ điều gì phức tạp hơn, tôi khuyên bạn nên sử dụng máy chủ phát trực tuyến, chẳng hạn như Icecast.

1

Hai điều nổi bật:

  1. Bạn đã có một bộ Content-Length. Nếu máy chủ của bạn được đặt thành tự động gzip đầu ra của bạn, điều này có thể gây rối với mọi thứ. Thử tắt Content-Length và xem có khắc phục được không.
  2. Bạn có khoảng một nghìn Content-Type s bộ. Vì đó là Mp3 mà bạn đang phục vụ, chỉ cần sử dụng audio/mpeg. Bạn có thể loại bỏ toàn bộ lệnh header() cuối cùng. Thật dễ dàng để được mang đi với tiêu đề HTTP.

Hãy dùng thử và cho chúng tôi biết cách hoạt động!

0

Xóa header("Content-Transfer-Encoding: binary"); Và bạn sẽ được đặt!

0

Đối với những giải pháp bạn cũng cần phải cấu hình xsendfile trong apache (mod_xsendfile) hoặc nginx HttpSecureLinkModule - họ sẽ cung cấp cho bạn chính xác mp3, do đó trình duyệt sẽ chơi nó một cách chính xác

0

Áp dụng tất cả các giải pháp này, trong đó có giá trị để ẩn ban đầu đường dẫn và tên tập tin, tiếc là không ngăn chặn từ tải trái phép. Thực tế là ứng dụng khách (trong trường hợp của tôi: Chrome) tải xuống tệp.

đây những dòng tôi đặt trên máy chủ của tôi:

<?php 
$dir = dirname($_SERVER['DOCUMENT_ROOT'])."/mp3"; 
$filename = $_GET['file']; 
$file = $dir."/".$filename; 

$extension = "mp3"; 
$mime_type = "audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3"; 

if(file_exists($file)){ 
    header('Content-type: {$mime_type}'); 
    header('Content-length: ' . filesize($file)); 
    header("Content-Transfer-Encoding: binary"); 
    header('Content-Disposition: filename="' . $filename); 
    header('X-Pad: avoid browser bug'); 
    header('Cache-Control: no-cache'); 
    readfile($file); 
}else{ 
    header("HTTP/1.0 404 Not Found"); 
} 
?> 

có hoặc không có dòng

header("Content-Transfer-Encoding: binary"); 

kết quả cuối cùng không thay đổi Thư mục/mp3 nằm vào

/home/myuser/ 

(do đó/home/myuser/mp3) và HTML công khai thư mục là

/home/myuser/public_html 

do đó gọi tên miền của tôi và đưa ra

/player.php?file=music.mp3 

nó tải về một tập tin gọi music.mp3 với tất cả các nội dung ban đầu.