【发布时间】:2011-01-05 13:41:27
【问题描述】:
我正在尝试使用 PHP 和 CURL 下载一些文件,但我没有看到使用默认建议文件名的简单方法(在 HTTP 响应标头中)
Content-Disposition:附件;文件名=foo.png
)。有没有更简单的方法然后获取完整的标题,解析文件名并重命名?
【问题讨论】:
我正在尝试使用 PHP 和 CURL 下载一些文件,但我没有看到使用默认建议文件名的简单方法(在 HTTP 响应标头中)
Content-Disposition:附件;文件名=foo.png
)。有没有更简单的方法然后获取完整的标题,解析文件名并重命名?
【问题讨论】:
这是一个没有 curl 的解决方案,但必须为此启用 url_fopen。
$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);
更新: Content-Disposition 中的文件名可以包含空格(在这种情况下,它们用单引号或双引号编写)。我用第二个 preg_match 块解决了这个问题。
【讨论】:
<?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);
我最初尝试使用php://memory 而不是/tmp/headers,因为使用临时文件来处理这类事情是草率的,但由于某种原因我无法让它工作。但至少你明白了……
或者,您可以使用CURLOPT_HEADERFUNCTION
【讨论】:
发出 HEAD 请求,匹配文件名(使用正则表达式),然后下载文件。
【讨论】: