Externe bestandsgrootte zonder bestand te downloaden

Is er een manier om de grootte van een extern bestand http://my_url/my_file.txtte krijgen zonder het bestand downloaden?


Antwoord 1, autoriteit 100%

Iets hierover gevonden hier:

Dit is de beste manier (die ik heb gevonden) om het formaat van een afstandsbediening te krijgen
het dossier. Houd er rekening mee dat HEAD-verzoeken niet de eigenlijke hoofdtekst van het verzoek krijgen,
ze halen gewoon de headers op. Dus een HEAD-verzoek indienen bij een bron
dat is 100 MB, duurt even lang als een HEAD-verzoek om a
bron die 1 KB is.

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

Gebruik:

$file_size = curl_get_file_size( "http://stackoverflow.com/questions/2602612/php-remote-file-size-without-downloading-file" );

Antwoord 2, autoriteit 62%

Probeer deze code

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

Antwoord 3, autoriteit 30%

Zoals een paar keer genoemd, is de beste manier om de informatie uit het veld Content-Lengthvan de antwoordheader op te halen.

Houd er echter rekening mee dat

  • de server die u zoekt, implementeert niet noodzakelijk de HEAD-methode(!)
  • het is absoluut niet nodig om handmatig een HEAD-verzoek te maken (dat, nogmaals, misschien niet eens wordt ondersteund) met behulp van fopenof iets dergelijks of zelfs om de curl-bibliotheek aan te roepen, wanneer PHP get_headers()(onthoud: KISS)

Gebruik van get_headers()volgt de KISS principeenwerkt zelfs als de server die u zoekt het HEAD-verzoek niet ondersteunt.

Dus, hier is mijn versie (gimmick: geeft door mensen leesbare geformatteerde grootte terug ;-)):

Samenvatting: https://gist.github.com/eyecatchup/f26300ffd7e50a92bc4d(versie met curl en get_headers)

get_headers()-Versie:

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

Gebruik:

$url = 'http://download.tuxfamily.org/notepadplus/6.6.9/npp.6.6.9.Installer.exe';
echo getRemoteFilesize($url); // echoes "7.51 MiB"

Aanvullende opmerking:de kop Content-Length is optioneel. Dus als algemene oplossing het is niet kogelvrij!



Antwoord 4, autoriteit 17%

Php-functie get_headers()werkt voor mij om de content-lengthals

te controleren

$headers = get_headers('http://example.com/image.jpg', 1);
$filesize = $headers['Content-Length'];

Voor meer details: PHP-functie get_headers()


Antwoord 5, autoriteit 14%

Natuurlijk. Dien een verzoek met alleen headers in en zoek naar de header Content-Length.


Antwoord 6, autoriteit 8%

beste oplossing in één regel :

echo array_change_key_case(get_headers("http://.../file.txt",1))['content-length'];

php is te lekker

function urlsize($url):int{
   return array_change_key_case(get_headers($url,1))['content-length'];
}
echo urlsize("http://.../file.txt");

Antwoord 7, autoriteit 7%

Ik weet het niet zeker, maar kun je hiervoor de get_headers-functie niet gebruiken?

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

Antwoord 8, autoriteit 3%

De eenvoudigste en meest efficiënte implementatie:

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

Antwoord 9, autoriteit 2%

Aangezien deze vraag al is getagd met “php” en “curl”, neem ik aan dat je weet hoe je Curl in PHP moet gebruiken.

Als je curl_setopt(CURLOPT_NOBODY, TRUE)instelt, dan dien je een HEAD-verzoek in en kun je waarschijnlijk de “Content-Length”-header van het antwoord controleren, dat alleen headers zal zijn.


Antwoord 10, autoriteit 2%

Probeer de onderstaande functie om de bestandsgrootte op afstand te krijgen

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

Antwoord 11, autoriteit 2%

Hier is een andere benadering die werkt met servers die geen HEAD-verzoeken ondersteunen.

Het gebruikt cURL om een ​​verzoek te doen voor de inhoud met een HTTP-bereikheader die om de eerste byte van het bestand vraagt.

Als de server bereikverzoeken ondersteunt (de meeste mediaservers zullen dat doen), ontvangt deze het antwoord met de grootte van de bron.

Als de server niet reageert met een bytebereik, zoekt hij naar een koptekst met de lengte van de inhoud om de lengte te bepalen.

Als de grootte wordt gevonden in een koptekst met een bereik of inhoudslengte, wordt de overdracht afgebroken. Als de grootte niet wordt gevonden en de functie begint met het lezen van de antwoordtekst, wordt de overdracht afgebroken.

Dit kan een aanvullende benadering zijn als een HEAD-verzoek resulteert in een 405-methode die niet wordt ondersteund.

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

Gebruik:

$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.";
}

Antwoord 12

De meeste antwoorden hier gebruiken CURL of zijn gebaseerd op leeskoppen. Maar in sommige bepaalde situaties kunt u een veel eenvoudigere oplossing gebruiken. Overweeg een opmerking over de documenten van filesize()over PHP. netto. U vindt daar een tip met de tekst: “Vanaf PHP 5.0.0 kan deze functie ook worden gebruikt met sommige URL-wrappers. Raadpleeg Ondersteunde protocollen en wrappersom te bepalen welke wrappers de stat()-familie van functionaliteit ondersteunen“.

Dus, als je server en PHP-parser correct zijn geconfigureerd, kun je gewoon de functie filesize()gebruiken, deze voorzien van de volledige URL, verwijzend naar een extern bestand, welke grootte je wilt hebben, en laat PHP alle magie doen.

Other episodes