it-swarm.com.de

Remote-Dateigröße ohne Herunterladen der Datei

Gibt es eine Möglichkeit, die Größe einer Remote-Datei http: //my_url/my_file.txt zu ermitteln, ohne die Datei herunterzuladen?

71
dassouki

Etwas dazu gefunden hier :

Hier ist der beste Weg (die ich gefunden habe), um die Größe einer Fernbedienung zu ermitteln Datei. Beachten Sie, dass HEAD -Anfragen nicht den eigentlichen Hauptteil der Anfrage erhalten, Sie rufen nur die Header ab. Eine Anforderung von HEAD an eine Ressource Das heißt, 100 MB dauert dieselbe Zeit wie eine HEAD - Anforderung an eine Ressource, die 1 KB ist.

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

Verwendungszweck:

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

Versuchen Sie diesen 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;
}
59
macki

Wie bereits erwähnt, müssen Sie die Informationen aus dem Feld Content-Length Des Antwortheaders abrufen.

Das sollten Sie jedoch beachten

  • der Server, den Sie untersuchen, implementiert nicht unbedingt die HEAD -Methode (!)
  • es ist absolut nicht erforderlich, eine HEAD -Anforderung manuell zu erstellen (die wiederum möglicherweise nicht einmal unterstützt wird), indem fopen oder dergleichen verwendet wird, oder sogar die Lockenbibliothek aufzurufen, wenn PHP hat get_headers() (denk dran: KISS )

Die Verwendung von get_headers() folgt dem KISS-Prinzip und funktioniert auch dann, wenn das Der von Ihnen getestete Server unterstützt die Anforderung HEAD nicht.

Also, hier ist meine Version (Gimmick: gibt eine lesbare formatierte Größe zurück ;-)):

Inhalt: https://Gist.github.com/eyecatchup/f26300ffd7e50a92bc4d (curl- und get_headers-Version)
get_headers () - Version:

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

Verwendungszweck:

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

Zusätzliche Anmerkung: Der Content-Length-Header ist optional. Daher ist es als allgemeine Lösung nicht kugelsicher !


30
eyecatchUp

Sicher. Erstellen Sie eine Anfrage, die nur aus Headern besteht, und suchen Sie nach dem Content-Length-Header.

14
ceejayoz

Die PHP-Funktion get_headers() prüft die content-length als 

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

Für weitere Details: PHP Funktion get_headers ()

7
Sanchit Gupta

Ich bin nicht sicher, aber konnten Sie die Funktion get_headers nicht dafür verwenden?

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

Die einfachste und effizienteste Implementierung:

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

Probieren Sie die unten stehende Funktion aus, um die Dateigröße der Remote-Datei zu erhalten

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;
}
2
Rahul Kaushik

Da diese Frage bereits mit "php" und "curl" gekennzeichnet ist, gehe ich davon aus, dass Sie Curl in PHP verwenden können.

Wenn Sie curl_setopt(CURLOPT_NOBODY, TRUE) setzen, stellen Sie eine HEAD - Anforderung und können möglicherweise den "Content-Length" -Header der Antwort überprüfen, der nur Header sein wird.

2
dkamins

Hier ist ein weiterer Ansatz, der mit Servern funktioniert, die keine HEAD-Anforderungen unterstützen.

Es verwendet cURL, um eine Anforderung für den Inhalt mit einem HTTP-Bereichsheader anzufordern, der nach dem ersten Byte der Datei fragt.

Wenn der Server Bereichsanforderungen unterstützt (die meisten Medienserver werden dies tun), erhält er die Antwort mit der Größe der Ressource.

Wenn der Server nicht mit einem Bytebereich antwortet, sucht er nach einem Inhaltslängenheader, um die Länge zu bestimmen.

Wenn die Größe in einem Bereichs- oder Inhaltslängenheader gefunden wird, wird die Übertragung abgebrochen. Wenn die Größe nicht gefunden wird und die Funktion beginnt, den Antworttext zu lesen, wird die Übertragung abgebrochen.

Dies könnte ein ergänzender Ansatz sein, wenn eine HEAD-Anforderung zu einer 405-Methode führt, die nicht unterstützt wird.

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

Verwendungszweck:

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

eine Linie beste Lösung:

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

pHP ist zu delicius

function urlsize($url):int{
   return array_change_key_case(get_headers($url,1))['content-length'];
}

echo urlsize("http://.../file.txt");
1
Samad

Die meisten Antworten hier verwenden entweder CURL oder basieren auf dem Lesen von Headern. In bestimmten Situationen können Sie eine einfachere Lösung verwenden. Beachten Sie die Hinweise zu den Dokumenten von filesize() in PHP.net . Dort finden Sie einen Tipp: "Ab PHP 5.0.0 kann diese Funktion auch mit einigen URL-Wrappern verwendet werden. Siehe Unterstützte Protokolle und Wrapper , um festzustellen, welche Wrapper stat unterstützen () Funktionsfamilie ".

Wenn also Ihr Server und der PHP - Parser ordnungsgemäß konfiguriert sind, können Sie einfach die Funktion filesize() verwenden, die vollständige URL eingeben, auf eine entfernte Datei zeigen, welche Größe Sie erhalten möchten, und PHP ausführen lassen das alles magisch.

1
trejder

Versuchen Sie folgendes: Ich benutze es und habe ein gutes Ergebnis erzielt.

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

Testen Sie jetzt wie folgt:

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;

Ergebnisse:

24,82 kiB

912 KiB

101,85 kiB

0
josef