I'm trying to download some files with PHP & CURL, but I don't see an easy way to use the default suggested filename (which is in the HTTP response header as
Content-Disposition: attachment; filename=foo.png
)开发者_如何学运维. Is there an easier way then get the full header, parse the file name and rename?
<?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);
I initially tried to use php://memory instead of /tmp/headers
, 'cause using temp files for this sort of thing is sloppy, but for some reason I couldn't get that working. But at least you get the idea...
Alternately, you could use CURLOPT_HEADERFUNCTION
Heres a solution without curl but url_fopen has to be enabled for this.
$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);
UPDATE: Filenames in Content-Disposition can have spaces (in that case they are written in single or double quotes). I solved this case with a second preg_match block.
Issue an HEAD request, match the filename (with regular expressions) and then download the file.
精彩评论