Удаленный размер файла без загрузки файла
есть ли способ получить размер удаленного файла http://my_url/my_file.txt без загрузки файла?
13 ответов:
нашел что-то об этом здесь:
вот лучший способ (который я нашел), чтобы получить размер пульта дистанционного управления файл. Обратите внимание, что запросы HEAD не получают фактическое тело запроса, они просто извлекают заголовки. Таким образом, делая запрос головы к ресурсу то есть 100MB займет столько же времени, сколько и запрос головы на a ресурс, который составляет 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 (!)
- нет абсолютно никакой необходимости вручную создавать запрос головы (который, опять же, может даже не поддерживаться) с помощью
fopen
или аналогично или даже для вызова библиотеки curl, когда PHP имеетget_headers()
(помните: К. И. С. С.)использование
get_headers()
следует принцип К. И. С. С.и работает, даже если сервер, который вы исследуете, не поддерживает запрос HEAD.Итак, вот моя версия (трюк: возвращает удобочитаемое размер ;-)):
суть: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 является необязательным. Таким образом, в качестве общего решения это не пуленепробиваемый!
Я не уверен, но не могли бы вы использовать функцию 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()
работает для меня, чтобы проверить content-length как$headers = get_headers('http://example.com/image.jpg', TRUE); $filesize = $headers['content-length'];
Для Более Подробной Информации:PHP функция get_headers ()
самая простая и эффективная реализация:
function remote_filesize($url, $fallback_to_download = false) { 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]; } if (!$fallback_to_download) { return false; } return strlen(stream_get_contents($fp)); }
поскольку этот вопрос уже помечен "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; }
большинство ответов здесь использует либо CURL, либо основаны на чтении заголовков. Но в некоторых определенных ситуациях вы можете использовать более простое решение. Рассмотрим примечание на
filesize()
' s docs on PHP.net. Вы найдете там подсказку, говорящую:"начиная с PHP 5.0.0, эта функция также может использоваться с некоторыми оболочками URL. См.поддерживаемые протоколы и фантики чтобы определить, какие обертки поддерживают семейство функций stat ()".Итак, если ваш сервер и PHP парсер правильно настроен, можно просто использовать
filesize()
функция, кормила его с полным URL, указывая на удаленный файл, размер которого вы хотите получить, и пусть PHP делает все волшебство.
вот еще один подход, который будет работать с серверами, которые не поддерживают
HEAD
запросы.он использует cURL для запроса содержимого с заголовком диапазона HTTP, запрашивающим первый байт файла.
если сервер поддерживает запросы диапазона (большинство медиа-серверов будет), то он получит ответ с размером ресурса.
если сервер не отвечает с диапазоном байтов, он будет искать заголовок content-length для определения длина.
если размер найден в заголовке диапазона или длины содержимого, передача прерывается. Если размер не найден и функция начинает считывать тело ответа, передача прерывается.
Это может быть дополнительный подход, если
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."; }
одна строка лучшее решение :
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");
попробуйте это: я использую его и получили хороший результат.
function getRemoteFilesize($url) { $file_headers = @get_headers($url, 1); if($size =getSize($file_headers)){ return $size; } elseif($file_headers[0] == "HTTP/1.1 302 Found"){ if (isset($file_headers["Location"])) { $url = $file_headers["Location"][0]; if (strpos($url, "/_as/") !== false) { $url = substr($url, 0, strpos($url, "/_as/")); } $file_headers = @get_headers($url, 1); return getSize($file_headers); } } return false; } function getSize($file_headers){ if (!$file_headers || $file_headers[0] == "HTTP/1.1 404 Not Found" || $file_headers[0] == "HTTP/1.0 404 Not Found") { return false; } elseif ($file_headers[0] == "HTTP/1.0 200 OK" || $file_headers[0] == "HTTP/1.1 200 OK") { $clen=(isset($file_headers['Content-Length']))?$file_headers['Content-Length']:false; $size = $clen; if($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 false; }
теперь, тест, как эти:
echo getRemoteFilesize('http://mandasoy.com/wp-content/themes/spacious/images/plain.png').PHP_EOL; echo getRemoteFilesize('http://bookfi.net/dl/201893/e96818').PHP_EOL; echo getRemoteFilesize('https://stackoverflow.com/questions/14679268/downloading-files-as-attachment-filesize-incorrect').PHP_EOL;
результаты:
24.82 KiB
912 KiB
101.85 KiB