Programing

파일 다운로드없이 원격 파일 크기

lottogame 2020. 10. 18. 08:20
반응형

파일 다운로드없이 원격 파일 크기


파일 을 다운로드하지 않고 http : //my_url/my_file.txt 원격 파일의 크기를 얻을 수있는 방법이 있습니까?


여기 에 대해 뭔가를 찾았습니다 .

원격 파일의 크기를 가져 오는 가장 좋은 방법은 다음과 같습니다. HEAD 요청은 요청의 실제 본문을 가져 오지 않고 헤더 만 검색합니다. 따라서 100MB의 리소스에 대한 HEAD 요청을 만드는 것은 1KB의 리소스에 대한 HEAD 요청과 동일한 시간이 걸립니다.

<?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 메서드 (!)를 구현하는 것은 아닙니다.
  • fopenPHP가있는 경우 get_headers()(기억 : KISS ) or alike를 사용하거나 심지어 curl 라이브러리를 호출 하기 위해 수동으로 HEAD 요청 (다시 말하지만 지원되지 않을 수도 있음)을 만들 필요가 없습니다 .

의 사용은 get_headers()다음 KISS 원칙 프로빙하고있는 서버가 HEAD 요청을 지원하지 않는 경우에도 작동합니다.

그래서, 여기 내 버전이 있습니다 (gimmick : 사람이 읽을 수있는 형식의 크기를 반환합니다 ;-)) :

요점 : 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 헤더는 선택 사항입니다. 따라서 일반적인 솔루션으로 방탄이 아닙니다 !



확실한. 헤더 만 요청하고 Content-Length헤더를 찾습니다 .


PHP 함수는 get_headers()수표의 나를 위해 작동 내용 길이를

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

자세한 내용은 PHP 함수 get_headers ()


잘 모르겠지만 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;

가장 간단하고 효율적인 구현 :

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"태그가 지정되어 있으므로 PHP에서 Curl을 사용하는 방법을 알고 있다고 가정합니다.

설정 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()PHP.net의 문서를 참고하십시오 . " PHP 5.0.0부터이 함수는 일부 URL 래퍼와 함께 사용할 수도 있습니다. stat () 기능 군을 지원하는 래퍼를 확인 하려면 지원되는 프로토콜 및 래퍼참조하세요. "라는 팁 이 있습니다 .

따라서 서버와 PHP 파서가 올바르게 구성되어 있으면 filesize()함수 를 사용 하고 전체 URL을 제공하고 원하는 크기의 원격 파일을 가리키고 PHP가 모든 마법을 수행하도록 할 수 있습니다.


다음은 HEAD요청을 지원하지 않는 서버에서 작동하는 또 다른 접근 방식입니다 .

cURL을 사용하여 파일의 첫 번째 바이트를 요청하는 HTTP 범위 헤더가있는 콘텐츠를 요청합니다.

서버가 범위 요청을 지원하는 경우 (대부분의 미디어 서버에서 지원) 리소스 크기에 대한 응답을받습니다.

서버가 바이트 범위로 응답하지 않으면 콘텐츠 길이 헤더를 찾아 길이를 결정합니다.

범위 또는 콘텐츠 길이 헤더에서 크기가 발견되면 전송이 중단됩니다. 크기를 찾을 수없고 함수가 응답 본문 읽기를 시작하면 전송이 중단됩니다.

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는 너무 섬세합니다

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.82KiB

912KiB

101.85 KiB

참고URL : https://stackoverflow.com/questions/2602612/remote-file-size-without-downloading-file

반응형