Usando o nome do arquivo padrão (content_disposition) ao fazer o download com CURL

Estou tentando baixar alguns arquivos com PHP e CURL, mas não vejo uma maneira fácil de usar o nome de arquivo sugerido padrão (que está no header da resposta HTTP como

Conteúdo-Disposição: anexo; filename = foo.png

). Existe uma maneira mais fácil de obter o header completo, analisar o nome do arquivo e renomear?

< ?php $targetPath = '/tmp/'; $filename = $targetPath . 'tmpfile'; $headerBuff = fopen('/tmp/headers', 'w+'); $fileTarget = fopen($filename, 'w'); $ch = curl_init('http://www.example.com/'); curl_setopt($ch, CURLOPT_WRITEHEADER, $headerBuff); curl_setopt($ch, CURLOPT_FILE, $fileTarget); curl_exec($ch); if(!curl_errno($ch)) { rewind($headerBuff); $headers = stream_get_contents($headerBuff); if(preg_match('/Content-Disposition: .*filename=([^ ]+)/', $headers, $matches)) { rename($filename, $targetPath . $matches[1]); } } curl_close($ch); 

Inicialmente, tentei usar php: // memory em vez de /tmp/headers , porque o uso de arquivos temporários para esse tipo de coisa é desleixado, mas por algum motivo não consegui que funcionasse. Mas pelo menos você consegue a ideia ...

Alternativamente, você pode usar CURLOPT_HEADERFUNCTION

Ela é uma solução sem curl, mas url_fopen deve ser habilitado para isso.

 $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 az eg (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); 

UPDATE: os nomes dos arquivos no Content-Disposition podem ter espaços (nesse caso eles são escritos em cotações simples ou duplas). Resolvi esse caso com um segundo bloco preg_match.

Emita um pedido HEAD, combine o nome do arquivo (com expressões regulares) e depois baixe o arquivo.