有没有办法在不下载文件的情况下获取远程文件http://my_url/my_file.txt的大小?PHP:无需下载文件即可获得远程文件大小
回答
找到东西这个here:
这里得到一个远程 文件大小的最佳方式(我发现)。请注意,HEAD请求不会获得请求的实际正文,它们只是检索标头。因此,对100MB的资源 发出HEAD请求将花费与到1KB的 资源的HEAD请求相同的时间量。
<?php
/**
* Returns the size of a file without downloading it, or -1 if the file
* size could not be determined.
*
* @param $url - The location of the remote file to download. Cannot
* be null or empty.
*
* @return The size of the file referenced by $url, or -1 if the size
* could not be determined.
*/
function curl_get_file_size($url) {
// Assume failure.
$result = -1;
$curl = curl_init($url);
// Issue a HEAD request and follow any redirects.
curl_setopt($curl, CURLOPT_NOBODY, true);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_USERAGENT, get_user_agent_string());
$data = curl_exec($curl);
curl_close($curl);
if($data) {
$content_length = "unknown";
$status = "unknown";
if(preg_match("/^HTTP\/1\.[01] (\d\d\d)/", $data, $matches)) {
$status = (int)$matches[1];
}
if(preg_match("/Content-Length: (\d+)/", $data, $matches)) {
$content_length = (int)$matches[1];
}
// http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
if($status == 200 || ($status > 300 && $status <= 308)) {
$result = $content_length;
}
}
return $result;
}
?>
用法:
$file_size = curl_get_file_size("http://stackoverflow.com/questions/2602612/php-remote-file-size-without-downloading-file");
当然。制作仅限标题的请求并查找Content-Length
标题。
因为这个问题已经被标记 “PHP” 和 “卷曲”,我假设你知道如何在PHP中使用卷曲。
如果你设置了curl_setopt(CURLOPT_NOBODY, TRUE)
那么你将发出一个HEAD请求,并且可能会检查响应的“Content-Length”标题,这将只是标题。
试试这个代码
function retrieve_remote_file_size($url){
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_NOBODY, TRUE);
$data = curl_exec($ch);
$size = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
curl_close($ch);
return $size;
}
试试下面的函数获取远程文件大小
function remote_file_size($url){
$head = "";
$url_p = parse_url($url);
$host = $url_p["host"];
if(!preg_match("/[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*/",$host)){
$ip=gethostbyname($host);
if(!preg_match("/[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*/",$ip)){
return -1;
}
}
if(isset($url_p["port"]))
$port = intval($url_p["port"]);
else
$port = 80;
if(!$port) $port=80;
$path = $url_p["path"];
$fp = fsockopen($host, $port, $errno, $errstr, 20);
if(!$fp) {
return false;
} else {
fputs($fp, "HEAD " . $url . " HTTP/1.1\r\n");
fputs($fp, "HOST: " . $host . "\r\n");
fputs($fp, "User-Agent: http://www.example.com/my_application\r\n");
fputs($fp, "Connection: close\r\n\r\n");
$headers = "";
while (!feof($fp)) {
$headers .= fgets ($fp, 128);
}
}
fclose ($fp);
$return = -2;
$arr_headers = explode("\n", $headers);
foreach($arr_headers as $header) {
$s1 = "HTTP/1.1";
$s2 = "Content-Length: ";
$s3 = "Location: ";
if(substr(strtolower ($header), 0, strlen($s1)) == strtolower($s1)) $status = substr($header, strlen($s1));
if(substr(strtolower ($header), 0, strlen($s2)) == strtolower($s2)) $size = substr($header, strlen($s2));
if(substr(strtolower ($header), 0, strlen($s3)) == strtolower($s3)) $newurl = substr($header, strlen($s3));
}
if(intval($size) > 0) {
$return=intval($size);
} else {
$return=$status;
}
if (intval($status)==302 && strlen($newurl) > 0) {
$return = remote_file_size($newurl);
}
return $return;
}
这是唯一一个在Ubuntu Linux apache服务器上为我工作的人。我在函数开始时不得不初始化$ size和$ status,否则按原样工作。 – 2013-11-12 12:50:25
大多数答案在这里使用任何卷曲或正在基础上读头。但在某些情况下,您可以使用更简单的解决方案。考虑关于filesize()
's docs on PHP.net的说明。你会发现有一个提示:“从PHP 5.0.0开始,这个函数也可以用于一些URL包装器,参考Supported Protocols and Wrappers来确定哪些包装器支持stat()系列的功能”。因此,如果您的服务器和PHP解析器配置正确,那么您可以简单地使用filesize()
函数,用完整的URL填充它,指向一个远程文件,您希望获得的大小,然后让PHP完成所有的魔术。
最简单和最有效的FPGA实现:
function remote_filesize($url) {
static $regex = '/^Content-Length: *+\K\d++$/im';
if (!$fp = @fopen($url, 'rb')) {
return false;
}
if (
isset($http_response_header) &&
preg_match($regex, implode("\n", $http_response_header), $matches)
) {
return (int)$matches[0];
}
return strlen(stream_get_contents($fp));
}
像魔术一样工作。谢谢。 – rottenoats 2016-02-26 14:23:57
我不知道,但不能使用get_headers功能呢?
$url = 'http://example.com/dir/file.txt';
$headers = get_headers($url, true);
if (isset($headers['Content-Length'])) {
$size = 'file size:' . $headers['Content-Length'];
}
else {
$size = 'file size: unknown';
}
echo $size;
在这个例子中,$ url的目标服务器可能利用get_headers来保持连接处于打开状态,直到PHP进程超时(通过非常缓慢地返回头部,而不足以让连接失效)。由于整个PHP进程可能受FPM限制,因此当多个“用户”同时访问您的get_headers脚本时,这可能允许一种缓慢的洛里斯攻击。 – 2016-10-12 16:14:00
如前所述几次,要走的路是检索与响应报头的Content-Length
场信息。
但是,你要注意,
- 你探测服务器不一定实现了HEAD方法(!)
- 但绝对不需要手工手艺使用
fopen
或相似,甚至调用curl库HEAD请求(再次,甚至可能不支持),PHP有get_headers()
时(记住:K.I.S.S.)
使用get_headers()
跟在K.I.S.S. principle和之后即使您正在探测的服务器不支持HEAD请求也能正常工作。
所以,这里是我的版本(噱头:返回人类可读格式的大小;-)):
要点:https://gist.github.com/eyecatchup/f26300ffd7e50a92bc4d(卷曲和get_headers版)
get_headers() - 版本:
<?php
/**
* Get the file size of any remote resource (using get_headers()),
* either in bytes or - default - as human-readable formatted string.
*
* @author Stephan Schmitz <[email protected]>
* @license MIT <http://eyecatchup.mit-license.org/>
* @url <https://gist.github.com/eyecatchup/f26300ffd7e50a92bc4d>
*
* @param string $url Takes the remote object's URL.
* @param boolean $formatSize Whether to return size in bytes or formatted.
* @param boolean $useHead Whether to use HEAD requests. If false, uses GET.
* @return string Returns human-readable formatted size
* or size in bytes (default: formatted).
*/
function getRemoteFilesize($url, $formatSize = true, $useHead = true)
{
if (false !== $useHead) {
stream_context_set_default(array('http' => array('method' => 'HEAD')));
}
$head = array_change_key_case(get_headers($url, 1));
// content-length of download (in bytes), read from Content-Length: field
$clen = isset($head['content-length']) ? $head['content-length'] : 0;
// cannot retrieve file size, return "-1"
if (!$clen) {
return -1;
}
if (!$formatSize) {
return $clen; // return size in bytes
}
$size = $clen;
switch ($clen) {
case $clen < 1024:
$size = $clen .' B'; break;
case $clen < 1048576:
$size = round($clen/1024, 2) .' KiB'; break;
case $clen < 1073741824:
$size = round($clen/1048576, 2) . ' MiB'; break;
case $clen < 1099511627776:
$size = round($clen/1073741824, 2) . ' GiB'; break;
}
return $size; // return formatted size
}
用法:
$url = 'http://download.tuxfamily.org/notepadplus/6.6.9/npp.6.6.9.Installer.exe';
echo getRemoteFilesize($url); // echoes "7.51 MiB"
附加说明: Content-Length标头是可选的。因此,作为一般解决方案它不是防弹!
这应该是被接受的答案。诚然,Content-Length是可选的,但它是获得文件大小而不下载它的唯一方法 - 而'get_headers'是获得'content-length'的最好方法。 – 2017-08-31 22:17:59
这是另一种方法,它可以与不支持HEAD
请求的服务器一起使用。
它使用cURL使用HTTP范围标头请求文件的第一个字节。
如果服务器支持范围请求(大多数媒体服务器将会),那么它将接收到具有资源大小的响应。
如果服务器没有响应一个字节范围,它会查找一个内容长度标头来确定长度。
如果在范围或内容长度标题中找到大小,传输将中止。如果未找到大小并且函数开始读取响应主体,则传输将中止。
如果HEAD
请求导致405
方法不支持的响应,这可能是一种补充方法。
/**
* Try to determine the size of a remote file by making an HTTP request for
* a byte range, or look for the content-length header in the response.
* The function aborts the transfer as soon as the size is found, or if no
* length headers are returned, it aborts the transfer.
*
* @return int|null null if size could not be determined, or length of content
*/
function getRemoteFileSize($url)
{
$ch = curl_init($url);
$headers = array(
'Range: bytes=0-1',
'Connection: close',
);
$in_headers = true;
$size = null;
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2450.0 Iron/46.0.2450.0');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_VERBOSE, 0); // set to 1 to debug
curl_setopt($ch, CURLOPT_STDERR, fopen('php://output', 'r'));
curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($curl, $line) use (&$in_headers, &$size) {
$length = strlen($line);
if (trim($line) == '') {
$in_headers = false;
}
list($header, $content) = explode(':', $line, 2);
$header = strtolower(trim($header));
if ($header == 'content-range') {
// found a content-range header
list($rng, $s) = explode('/', $content, 2);
$size = (int)$s;
return 0; // aborts transfer
} else if ($header == 'content-length' && 206 != curl_getinfo($curl, CURLINFO_HTTP_CODE)) {
// found content-length header and this is not a 206 Partial Content response (range response)
$size = (int)$content;
return 0;
} else {
// continue
return $length;
}
});
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($curl, $data) use ($in_headers) {
if (!$in_headers) {
// shouldn't be here unless we couldn't determine file size
// abort transfer
return 0;
}
// write function is also called when reading headers
return strlen($data);
});
$result = curl_exec($ch);
$info = curl_getinfo($ch);
return $size;
}
用法:
$size = getRemoteFileSize('http://example.com/video.mp4');
if ($size === null) {
echo "Could not determine file size from headers.";
} else {
echo "File size is {$size} bytes.";
}
PHP函数get_headers()
作品为我检查内容长度作为
$headers = get_headers('http://example.com/image.jpg', TRUE);
$filesize = $headers['content-length'];
对我来说(使用nginx)标题是Content-Length – Pangamma 2017-09-19 18:11:58
一行最佳解决方案:
echo array_change_key_case(get_headers("http://.../file.txt",1))['content-length'];
PHP是太delicius
function urlsize($url):int{
return array_change_key_case(get_headers($url,1))['content-length'];
}
echo urlsize("http://.../file.txt");
- 1. 无需打开文件即可文件大小
- 2. 获得在KB/MB PHP远程文件大小/ GB格式
- 3. PHP,确定远程文件的大小
- 4. PHP强制下载远程文件
- 5. PHP - 笨下载远程文件
- 6. 使用PHP下载远程文件(2GB)
- 7. 下载远程文件
- 8. 下载大量小文件
- 9. Jsp下载文件大小
- 10. 下载文件大小--JavaME
- 11. 获得远程文件的大小(不使用Content-Length字段)
- 12. solr查询 - 无需扫描文件即可获得结果
- 13. 使用文件大小读取远程文件大小
- 14. 在PHP中可靠下载大文件
- 15. 获取远程托管文件的文件大小
- 16. 使用PHP/cURL下载远程文件:更强大一点
- 17. 如何通过使用PHP无需下载即可比较2个文件?
- 18. 如何让人们无需解释代码即可下载.php文件?
- 19. 如何获得远程存储的图像文件的大小? (PHP)
- 20. 如何获取多个文件下载的文件大小
- 21. 在android中下载文件之前获取文件大小
- 22. 在通过HTTP下载文件之前获取文件大小
- 23. 获取文件请求的文件大小信息下载
- 24. 无需下载即可从远程jpeg生成缩略图
- 25. 如何在开始下载之前获取远程文件的大小?
- 26. 无法下载文件 - PHP
- 27. 用PHP覆盖文件后无法获得新的文件大小?
- 28. PHP强制下载远程文件而无需通过我们的服务器
- 29. 以编程方式从远程文件使用delphi获取文件大小,然后下载它
- 30. Python ftplib在下载之前无法获取文件的大小?
我读的是较早的,不知道,如果内容长度指长度或文件大小 – dassouki 2010-04-08 18:59:45
好,如果该请求返回一个文件,请求大小*是*文件大小 – Gareth 2010-04-08 19:01:07
但请记住,在没有内容长度的情况下,_can_可能是响应。 – VolkerK 2010-04-08 19:26:25