php - force - Freed mucho más lento para descargar que readfile
php readfile path (3)
El motivo es 2014. El sistema operativo obtiene una porción de datos de 4096 bytes muy rápido y otros. Pero si escribe 2014, entonces el sistema operativo intenta leer datos del archivo por un byte para calcularlo. Es por eso que toma tanto tiempo. Cambiar 2014 a 4096
Estoy publicando descargas de una URL a mis usuarios a través de un script PHP. Cuando uso readfile()
obtengo la máxima velocidad de descarga que puede admitir mi conexión (aproximadamente 2.5MB / s), sin embargo cuando uso fopen, fread, fclose
route la velocidad de descarga es muy, muy lenta (alrededor de 1-2KB / s).
Aquí está mi código:
header(''Content-Description: File Transfer'');
header(''Content-Type: application/octet-stream'');
header(''Content-Disposition: attachment; filename='' . $filename);
header(''Content-Transfer-Encoding: binary'');
header(''Expires: 0'');
header(''Cache-Control: must-revalidate'');
header(''Pragma: public'');
header(''Content-Length: '' . $filesize);
ob_clean();
flush();
$file = fopen($url, ''rb'');
while(!feof($file)) {
echo fread($file, 2014);
}
y el código readfile es simplemente readfile($link);
.
No puedo usar simplemente la función readfile()
por dos razones, una es que quiero restringir la velocidad de descarga de los usuarios (lo cual puedo hacer con fread
leyendo solo tantos datos) y también quiero fread
cuánto un usuario está descargando (puedo hacer esto con readfile()
pero no cuenta descargas parciales).
¿Alguien sabe por qué esto podría estar pasando o cómo puedo solucionarlo? Por lo que sé, readfile()
es solo un contenedor para fopen, fread and fclose
así que no entiendo lo que está pasando mal.
Editar: Terminó yendo con cURL para esto.
$curl = curl_init();
$options = array(
CURLOPT_URL => $rdLink,
CURLOPT_FAILONERROR => true,
CURLOPT_BINARYTRANSFER => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_WRITEFUNCTION => ''readResponse''
);
curl_setopt_array($curl, $options);
if(!curl_exec($curl)) {
header(''Location: http://whatever.com'');
exit;
}
curl_close($curl);
function readResponse($ch, $data) {
$length = mb_strlen($data, ''8bit'');
echo $data;
return $length;
}
Puede ser el almacenamiento en búfer (o incluso limitar la velocidad) en algún lugar de PHP o Apache. Intenta cambiar:
while(!feof($file)) {
echo fread($file, 2014);
}
A:
while(!feof($file)) {
$s=fread($file, 2014);
if($s===false)break; //Crude
echo $s;
@ob_flush();@flush();
}
(El prefijo @
es porque pueden quejarse sobre los búferes vacíos).
Como dijo mr.freshwater, deberías tener una comprobación de errores en tu llamada de fread
, así que he agregado algo básico arriba.
Utilice stream_context_create () y stream_get_contents ()
$context = stream_context_create();
$file = fopen($url, ''rb'', FALSE, $context);
while(!feof($file))
{
//usleep(1000000);
echo stream_get_contents($file, 2014);
}
También podría tratar de hacer que la longitud de lectura del archivo sea más grande y colocar un usleep () para ralentizar la ejecución. Las funciones de transmisión parecen ser recomendadas sobre fread para la última versión de PHP de todos modos. También le conviene añadir una @ delante de fread () o stream_get_contents () para suprimir cualquier error, al menos en producción. Sin él, y un pequeño contratiempo, y tienes un archivo corrupto.