Есть ли способ получить размер удаленного файла http: //my_url/my_file.txt без непосредственной загрузки этого файла?
Ответ 1
Вот лучший способ (который я нашел) получить размер удаленного файла. Обратите внимание, что запросы HEAD не получают фактического тела запроса, они просто извлекают заголовки. Таким образом, выполнение запроса HEAD к ресурсу размером 100 Мб займет столько же времени, что и запрос HEAD к ресурсу размером 1 Кб.
<?php
/**
* Возвращает размер файла без его загрузки, или -1, если размер файла
* не может быть определен.
*
* @param $url - Расположение удаленного файла для загрузки. Не может
* быть null или пустой строкой.
*
* @return Размер файла, на который ссылается $url, или -1, если размер не удалось определить.
* */
function curl_get_file_size( $url ) {
// Предполагаем неудачу.
$result = -1;
$curl = curl_init( $url );
// Вызовите запрос HEAD и проследите за всеми перенаправлениями.
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" );
Ответ 2
Попробуйте этот код:
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;
}
Ответ 3
Как упоминалось несколько раз, нужно получить информацию из Content-Length поля заголовка ответа.
Однако следует отметить, что:
сервер, который вы исследуете, не обязательно реализует метод HEAD (!);
нет абсолютно никакой необходимости вручную создавать запрос HEAD (который, опять же, может даже не поддерживаться), используя fopen или аналогично, или даже вызывать библиотеку curl, когда PHP имеет get_headers();
использование get_headers() следует принципу KISS и работает, даже если исследуемый сервер не поддерживает запрос HEAD.
Итак, вот моя версия:
<?php
/**
* Получение размера файла любого удаленного ресурса (с помощью get_headers()),
* либо в байтах, либо - по умолчанию - в виде человекочитаемой форматированной строки.
*
* @author Stephan Schmitz <eyecatchup@gmail.com>
* @license MIT <http://eyecatchup.mit-license.org/>
* @url <https://gist.github.com/eyecatchup/f26300ffd7e50a92bc4d>
*
* @param string $url Принимает URL удаленного объекта.
* @param boolean $formatSize Возвращать ли размер в байтах или в форматированном виде.
* @param boolean $useHead Использовать ли запросы HEAD. Если false, используется GET.
* @return string Возвращает человекочитаемый форматированный размер.
* или размер в байтах (по умолчанию: форматированный).
*/
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:
$clen = isset($head['content-length']) ? $head['content-length'] : 0;
// невозможно получить размер файла, возвращается "-1"
if (!$clen) {
return -1;
}
if (!$formatSize) {
return $clen; // возвращается размер в байтах
}
$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; // возврат форматированного размера
}
Применение:
$url = 'http://download.tuxfamily.org/notepadplus/6.6.9/npp.6.6.9.Installer.exe';
echo getRemoteFilesize($url); // echoes "7.51 MiB"
Дополнительное примечание: заголовок Content-Length не является обязательным. Таким образом, как общее решение это не 100 процентно!
Ответ 4
Самая простая и эффективная реализация:
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));
}
Web