Heres une solution sans boucle, mais url_fopen doit être activé pour cela.
$response_headers = get_headers($url,1);
// first take filename from url
$filename = basename($url);
// if Content-Disposition is present and file name is found use this
if(isset($response_headers["Content-Disposition"]))
{
// this catches filenames between Quotes
if(preg_match('/.*filename=[\'\"]([^\'\"]+)/', $response_headers["Content-Disposition"], $matches))
{ $filename = $matches[1]; }
// if filename is not quoted, we take all until the next space
else if(preg_match("/.*filename=([^ ]+)/", $response_headers["Content-Disposition"], $matches))
{ $filename = $matches[1]; }
}
// if no Content-Disposition is found use the filename from url
// before using the filename remove all unwanted chars wich are not on a-z e.g. (I the most chars which can be used in filenames, if you like to renove more signs remove them from the 1. parameter in preg_replace
$filename = preg_replace("/[^a-zA-Z0-9_#\(\)\[\]\.+-=]/", "",$filename);
// at last download/copy the content
copy($url, $filename);
MISE À JOUR: noms de fichiers dans Content-Disposition peut avoir des espaces (dans ce cas, ils sont écrits entre guillemets simples ou doubles). J'ai résolu ce cas avec un deuxième bloc preg_match.
L'émission de deux demandes est inutile. Et il n'y a aucune garantie que la cible supporte réellement HEAD. –