2010-03-01 13 views
9

que tiene una situación muy similar a la persona que le preguntó: Can I serve MP3 files with PHP? Básicamente estoy tratando de proteger los archivos mp3 de descarga directa, por lo que los usuarios tienen que ir a través de PHP para obtener autenticado primero. Aquí está mi código: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); 

Aquí es mi problema: El archivo sólo juega un pequeño trozo del principio (a través de Quicktime en el navegador) y luego se detiene - Quicktime parece pensar que la longitud del archivo sólo siempre y cuando el trozo se las arregló para descargar. Cuando vuelvo a cargar, reproduce un fragmento un poco más grande, lo que sea que haya logrado descargar hasta ese momento.

¿Hay algún problema en los encabezados que estoy enviando? ¿Cómo podría transmitir ese archivo? ¿Es un problema si un swf está leyendo de ese archivo?

Gracias!


Gracias a todos por todas las respuestas. Aunque ninguna de estas cosas fue exactamente lo que resolvió el problema, muchas de ellas me enviaron en la dirección correcta. Muy apreciado. Para la solución completa ver mi respuesta a continuación

+0

Supongo que no tiene ese error tipográfico ("Encabezado") en su código real? Además, no necesitas el hack X-Pad. Esto solo es necesario para el antiguo Netscape (ver http://george.hotelling.net/90percent/geekery/why_is_apache_sending_a_xpad_header.php). No necesita Content-Transfer-Encoding, y solo debe especificar Content-Type una vez (audio/mpeg está bien). –

+0

@Matthew Flaschen: las funciones de PHP no distinguen entre mayúsculas y minúsculas, por lo que solo se trata de un problema de coherencia. El tipo de contenido puede ser el verdadero problema aquí. – Piskvor

Respuesta

6

Esto es lo que hizo el truco.

$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

Es posible que desee hacer alguna validación/desinfección en $ _GET ['file'] antes de leerlo ... – Simon

+0

Compruebo si el archivo existe 'if (file_exists ($ file)) {' ... ¿Es eso lo que quiso decir? ? –

+4

No, él no quiso decir eso. Piensa por ti mismo, qué pasa si alguien intenta esto http://yoursite.com/yourscript.php?file=../../../home/someonesgirlfriend/secretdiary.doc – Jonny

1

si su servidor se ejecuta en Apache o lighty, yo sugeriría que se mira en x-sendfile

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

esto le permite manejar la autenticación en su aplicación php, pero permitamos que su servidor web maneje la transmisión del archivo. la mejora del rendimiento que obtenga debe ser un beneficio adicional agradable

1

Puede probar HTTP chunking. Establezca el encabezado "Transfer-Encoding" en "chunked", luego genere el tamaño de cada fragmento antes de enviarlo. Termine cada tamaño de fragmento y fragmento con un CRLF.

Para cualquier cosa más compleja, recomiendo usar un servidor de transmisión, como Icecast.

1

Dos cosas se destacan:

  1. Tienes un conjunto Content-Length. Si su servidor está configurado para gzip automáticamente su salida, esto puede meterse con cosas. Intente apagar Content-Length y vea si eso lo soluciona.
  2. Tienes alrededor de mil Content-Type s establecidos. Dado que es Mp3 que está sirviendo, simplemente use audio/mpeg. De hecho, puede deshacerse de todo el último comando header(). Es fácil dejarse llevar por los encabezados HTTP.

Pruébalo y cuéntanos cómo te va!

0

Retire header("Content-Transfer-Encoding: binary"); Y le fijarán!

0

Para estas soluciones también es necesario configurar xsendfile en Apache (mod_xsendfile) o nginx HttpSecureLinkModule - que le dará mp3 exacta, por lo que el navegador se reproducirán correctamente

0

La aplicación de todas estas soluciones, que son válidos para ocultar la La ruta de acceso y el nombre de archivo originales, lamentablemente no impiden la descarga no autorizada. De hecho, el cliente (en mi caso: Chrome) descarga el archivo.

Aquí las líneas que pongo en mi servidor:

<?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"); 
} 
?> 

con o sin la línea

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

el resultado final no cambia El directorio/mp3 se encuentra en

/home/myuser/ 

(así/home/myuser/mp3) y el HTML público directorio es

/home/myuser/public_html 

llamar así mi dominio y dando

/player.php?file=music.mp3 

se descarga un archivo llamado music.mp3 con todo el contenido original.