Для того, чтобы определить имя скачиваемого файла, необходимо прочитать заголовки, пришедшие вместе с ним. Сделать это можно с помощью cURL. На самом деле других способов я пока не видел.
Вам нужен заголовок "Content-Disposition". Вот пример получения имени файла и самого файла:
$header = fopen("tmp/headers", 'w+');
$book_file = fopen("tmp/tmpfile", 'w');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_WRITEHEADER, $header);
curl_setopt($ch, CURLOPT_FILE, $book_file);
curl_setopt($ch, CURLOPT_COOKIE, "PHPSESSID=xxxxxxxxxxx");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
fclose($book_file);
$disposition_regexp = '/^Content-Disposition: .*?filename=(?<f>[^\s]+|\x22[^\x22]+\x22)\x3B?.*$/m';
$filename = "";
rewind($header);
$header = stream_get_contents($header);
if (preg_match($disposition_regexp, $header, $disposition)) {
$filename = trim($disposition['f'],' ";');
if ($filename && $book_file) {
$full_path = $books_folder.$ext."/".$filename;
$rename_success = rename("tmp/tmpfile", $full_path);
echo "Book downloaded: ID - ".$book_id."; Name - ".iconv("UTF-8", "WINDOWS-1251", $title).".".$ext.PHP_EOL;
}
}
Объясню вкратце, что здесь происходит. При запросе, мы получаем в отдельные переменные заголовки и само содержимое файла, $header и $book_file соответственно. Потом регулярным выражением находим, есть ли среди заголовков нужный нам с названием файла и переименовываем временный файл, при необходимости перемещая его в нужную директорию.