A continuación se muestra un ejemplo completo que utiliza una clase. El análisis de encabezado es más elaborado de lo que puede ser, porque estaba sentando la base para el almacenamiento completo de encabezado jerárquico.
Acabo de notar que init() debería restablecer muchas más variables si quiere reutilizar la instancia para más URL, pero al menos debería proporcionarle una base de cómo descargar un archivo a un nombre de archivo enviado por el servidor.
<?php
/*
* vim: ts=4 sw=4 fdm=marker noet tw=78
*/
class curlDownloader
{
private $remoteFileName = NULL;
private $ch = NULL;
private $headers = array();
private $response = NULL;
private $fp = NULL;
private $debug = FALSE;
private $fileSize = 0;
const DEFAULT_FNAME = 'remote.out';
public function __construct($url)
{
$this->init($url);
}
public function toggleDebug()
{
$this->debug = !$this->debug;
}
public function init($url)
{
if(!$url)
throw new InvalidArgumentException("Need a URL");
$this->ch = curl_init();
curl_setopt($this->ch, CURLOPT_URL, $url);
curl_setopt($this->ch, CURLOPT_HEADERFUNCTION,
array($this, 'headerCallback'));
curl_setopt($this->ch, CURLOPT_WRITEFUNCTION,
array($this, 'bodyCallback'));
}
public function headerCallback($ch, $string)
{
$len = strlen($string);
if(!strstr($string, ':'))
{
$this->response = trim($string);
return $len;
}
list($name, $value) = explode(':', $string, 2);
if(strcasecmp($name, 'Content-Disposition') == 0)
{
$parts = explode(';', $value);
if(count($parts) > 1)
{
foreach($parts AS $crumb)
{
if(strstr($crumb, '='))
{
list($pname, $pval) = explode('=', $crumb);
$pname = trim($pname);
if(strcasecmp($pname, 'filename') == 0)
{
// Using basename to prevent path injection
// in malicious headers.
$this->remoteFileName = basename(
$this->unquote(trim($pval)));
$this->fp = fopen($this->remoteFileName, 'wb');
}
}
}
}
}
$this->headers[$name] = trim($value);
return $len;
}
public function bodyCallback($ch, $string)
{
if(!$this->fp)
{
trigger_error("No remote filename received, trying default",
E_USER_WARNING);
$this->remoteFileName = self::DEFAULT_FNAME;
$this->fp = fopen($this->remoteFileName, 'wb');
if(!$this->fp)
throw new RuntimeException("Can't open default filename");
}
$len = fwrite($this->fp, $string);
$this->fileSize += $len;
return $len;
}
public function download()
{
$retval = curl_exec($this->ch);
if($this->debug)
var_dump($this->headers);
fclose($this->fp);
curl_close($this->ch);
return $this->fileSize;
}
public function getFileName() { return $this->remoteFileName; }
private function unquote($string)
{
return str_replace(array("'", '"'), '', $string);
}
}
$dl = new curlDownloader(
'https://dl.example.org/torrent/cool-movie/4358-hash/download.torrent'
);
$size = $dl->download();
printf("Downloaded %u bytes to %s\n", $size, $dl->getFileName());
?>
¿La respuesta es correcta para usted? Si es así, por favor, el más útil, ya que es correcto para la ayuda de los demás. –