PHP: удаленный размер файла без загрузки файла

Есть ли способ получить размер удаленного файла http: //my_url/my_file.txt без загрузки файла?

Нашел что-то об этом здесь :

Вот лучший способ (который я нашел), чтобы получить размер удаленного файла. Обратите внимание, что запросы HEAD не получают фактический объем запроса, они просто извлекают заголовки. Таким образом, для запроса HEAD ресурсу, который составляет 100 МБ, потребуется столько же времени, сколько и запрос HEAD для ресурса 1 КБ.

<?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" ); 

Попробуйте этот код

 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; } 

Как уже упоминалось несколько раз, путь к поиску – получение информации из поля Content-Length заголовка ответа .

Однако следует отметить, что

  • сервер, который вы исследуете, не обязательно реализует метод HEAD (!)
  • нет необходимости вручную обрабатывать запрос HEAD (который, опять же, может даже не поддерживаться) с использованием fopen или подобным образом или даже для вызова библиотеки curl, когда PHP имеет get_headers() (помните: KISS )

Использование get_headers() следует принципу KISS и работает, даже если сервер, который вы исследуете, не поддерживает запрос HEAD.

Итак, вот моя версия (трюк: возвращает человеко-читаемый формат формата ;-)):

Gist: https://gist.github.com/eyecatchup/f26300ffd7e50a92bc4d (версия curl и 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 <eyecatchup@gmail.com> * @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 .

Поскольку этот вопрос уже отмечен как «php» и «curl», я предполагаю, что вы знаете, как использовать Curl в PHP.

Если вы установите curl_setopt(CURLOPT_NOBODY, TRUE) вы сделаете запрос HEAD и, вероятно, можете проверить заголовок «Content-Length» ответа, который будет только заголовком.

Попробуйте использовать функцию ниже, чтобы получить размер удаленного файла

 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; } 

Простейшая и эффективная реализация:

 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)); } 

Я не уверен, но разве вы не могли использовать функцию 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; 

Функция php get_headers() работает для меня, чтобы проверить длину содержимого как

 $headers = get_headers('http://example.com/image.jpg', TRUE); $filesize = $headers['content-length']; 

Дополнительные сведения: PHP-функция get_headers ()

Большинство ответов здесь использует либо CURL, либо основывается на заголовках чтения. Но в некоторых определенных ситуациях вы можете использовать более легкое решение. Обратите внимание на документы filesize() на PHP.net . Вы найдете там отзыв: « Начиная с PHP 5.0.0, эта функция также может использоваться с некоторыми оболочками URL-адресов. Обратитесь к поддерживаемым протоколам и упаковщикам, чтобы определить, какие обертки поддерживают семейство функций stat () ».

Итак, если ваш сервер и парсер PHP правильно настроены, вы можете просто использовать функцию filesize() , загрузить его с полным URL-адресом, указывая на удаленный файл, какой размер вы хотите получить, и пусть PHP сделает все волшебство.

Вот еще один подход, который будет работать с серверами, которые не поддерживают запросы HEAD .

Он использует cURL для запроса запроса на контент с заголовком диапазона HTTP, запрашивающим первый байт файла.

Если сервер поддерживает запросы диапазона (большинство медиа-серверов), то он получит ответ с размером ресурса.

Если сервер не отвечает с байтом, он будет искать заголовок длины содержимого для определения длины.

Если размер найден в заголовке диапазона или длины содержимого, передача прерывается. Если размер не найден, и функция начинает считывать тело ответа, передача прерывается.

Это может быть дополнительным подходом, если запрос HEAD приводит к 405 метода 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."; } 

одна линия лучшее решение:

 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");