Limitar la velocidad de descarga de archivos en PHP
En más de una ocasión queremos facilitar un archivo a nuestros usuarios por motivos varios. Por lo general lo alojaremos en algún hosting gratuíto para no incidir demasiado en el rendimiento de nuestro servidor: si no sabemos la aceptación que va a tener el archivo en cuestión podemos encontrarnos con la desagradable sorpresa de que nuestro servidor pase más tiempo caído que de pie, debido a cuellos de botella generados en horarios punta de descarga.
Tengo en mente hace algún tiempo el desarrollo de una e-biblioteca, en la cual es mi intención que se descarguen ebooks en formato pdf, y ante el problema del ancho de banda para alojar, pongamos por ejemplo, un par de gigas de ebooks especializados, he montado una función en php que te permite limitar la velocidad de descarga de los archivos sin retocar nada del lado del servidor.
-
<?php
-
function enviar_archivo($archivo, $speed = 100) {
-
// Veamos.. existe el fichero ?
-
}
-
// Recolectamos información sobre el archivo
-
// Asignamos el Content-Type adecuado a cada tipo de archivo, esto se
-
// puede configurar al gusto, yo he incluído los más comunes para los
-
// ebooks: exe, zip, lit, pdf, mp3, html, html
-
switch($archivo_extension) {
-
case "exe":
-
$ctype="application/octet-stream";
-
break;
-
case "zip":
-
$ctype="application/zip";
-
break;
-
case "lit":
-
$ctype="application/lit";
-
break;
-
case "pdf":
-
$ctype="application/pdf";
-
break;
-
case "mp3":
-
$ctype="audio/mpeg3";
-
break;
-
case "htm":
-
case "html":
-
$ctype="text/html";
-
break;
-
case "txt":
-
$ctype="text/plain";
-
break;
-
// Debemos tener cuidado con no dejar descargar por este
-
// método ficheros sensibles tales como ficheros .php, .inc, etc...
-
case "php":
-
case "inc":
-
break;
-
default:
-
$ctype="application/force-download";
-
}
-
// Empezamos con los headers
-
// Meramente estético, sustituímos los posibles guiones bajos ( _ )
-
// por espacios en el nombre del fichero para bajar archivos más
-
// legibles. Ej: "fichero_a_bajar.pdf" se convierte en "fichero a bajar.pdf"
-
// Forzamos la descarga en lugar de la apertura
-
$header='Content-Disposition: attachment; filename='.$archivo_nombre_limpio;
-
-
-
-
// Si el navegador nos solicita el http_range...
-
// entonces le enviamos sólo el trozo que falta.
-
// (Mundialmente conocido como "resume")
-
$tamano2=$tamano-1;
-
$nueva_longitud=$tamano2-$rango;
-
} else {
-
// Si no le enviamos todo el pack
-
$tamano2=$tamano-1;
-
}
-
// Una vez tomadas estas decisiones, sólo queda abrir el archivo...
-
// localizar el inicio de la parte que queremos enviar...
-
// y empezar a enviar. Aqui es donde se produce la magia... en base
-
// a la variable de velocidad, leemos ese número de Ks del archivo,
-
// lo enviamos... y nos "dormimos" un segundo. Esta forzada chapuza
-
// produce exactamente el efecto deseado... ralentizar la descarga a
-
// los X k/s que deseemos por cada envío.
-
// Nos aseguramos de no producir un timeout por sobrepasar el
-
// tiempo máximo de ejecución de PHP en caso de archivos
-
// demasiado grandes.
-
// Ponemos los datos en el buffer...
-
// Lanzamos el contenido del buffer...
-
// Y a dormir...
-
}
-
// Proceso completado, archivo descargado,
-
// todo el "pescao vendío"
-
exit;
-
}
-
// Y finalmente un ejemplo tonto de uso de la función
-
enviar_archivo("fichero.pdf",100);
-
?>
Términos relacionados: application octet stream, strrchr, mpeg3, basename, motivos, gusto, content type
el # Miércoles, 6 de Diciembre del 2006 a las 23:33
muy bueno el script, pero tengo una duda..
en la linea que dice:
fseek($puntero_al_fichero, $posicion_inicio);
la variable “$posicion_inicio” de donde sale??
porque: Notice: Undefined variable: posicion_inicio…
gracias.
el # Jueves, 7 de Diciembre del 2006 a las 11:09
El código es tan sólo una “prueba de concepto”, como ves hay código que aún no sirve, ya que en el momento de escribir esto me peleaba con la función “resume”.
Para usarlo como está creo que bastará con que sustituyas la variable $posicion_inicio por un simple 0.
fseek($puntero_al_fichero,0);
el # Lunes, 20 de Agosto del 2007 a las 20:13
No se que pasa pero los archivos ZIP se bajan corruptos….
He probado con los RAR y con las imagenes y se bajan bien, pero no con los ZIP
el # Martes, 21 de Agosto del 2007 a las 02:18
le he quitado lo del http_range y ahora los zips se bajan bien.
Muchas gracias por la funcion.