Web

Определение размера удаленного файла без загрузки файла

Есть ли способ получить размер удаленного файла 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

Что лучше использовать при освобождении памяти в PHP: unset() или $var=null

Типы тега <іnput> HTML 5, для создания каких элементов управления используется
Web

Типы тега <іnput> HTML 5, для создания каких элементов управления используется

Web

Пример использования bind_result/get_result

Лучшие бесплатные платформы для создания сайтов без особых навыков
Web

Лучшие бесплатные платформы для создания сайтов без особых навыков

×