php 无需下载文件的远程文件大小

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2602612/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 07:04:57  来源:igfitidea点击:

Remote file size without downloading file

phpcurl

提问by dassouki

Is there a way to get the size of a remote file http://my_url/my_file.txtwithout downloading the file?

有没有办法在不下载文件的情况下获取远程文件http://my_url/my_file.txt的大小?

回答by NebuSoft

Found something about this here:

在这里找到了一些东西:

Here's the best way (that I've found) to get the size of a remote file. Note that HEAD requests don't get the actual body of the request, they just retrieve the headers. So making a HEAD request to a resource that is 100MB will take the same amount of time as a HEAD request to a resource that is 1KB.

这是获取远程文件大小的最佳方法(我发现的)。请注意, 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;
}
?>

Usage:

用法:

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

回答by macki

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

回答by eyecatchUp

As mentioned a couple of times, the way to go is to retrieve the information from the response header's Content-Lengthfield.

正如多次提到的,要走的路是从响应头的Content-Length字段中检索信息。

However, you should note that

但是,您应该注意的是

  • the server you're probing not necessarily implements the HEAD method(!)
  • there's absolutely no need to manually craft a HEAD request (which, again, might not even be supported) using fopenor alike or even to invoke the curl library, when PHP has get_headers()(remember: K.I.S.S.)
  • 您正在探测的服务器不一定实现 HEAD 方法(!)
  • 绝对不需要手动制作 HEAD 请求(同样,可能甚至不支持)使用fopen或类似甚至调用 curl 库,当 PHP 有时get_headers()(记住:KISS

Use of get_headers()follows the K.I.S.S. principleandworks even if the server you're probing does not support the HEAD request.

使用get_headers()遵循KISS 原则即使您正在探测的服务器不支持 HEAD 请求也能正常工作。

So, here's my version (gimmick: returns human-readable formatted size ;-)):

所以,这是我的版本(噱头:返回人类可读的格式化大小;-)):

Gist: https://gist.github.com/eyecatchup/f26300ffd7e50a92bc4d(curl and get_headers version)
get_headers()-Version:

要点: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 <[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
}

Usage:

用法:

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


Additional note:The Content-Length header is optional. Thus, as a general solution it isn't bullet proof!

附加说明:Content-Length 标头是可选的。因此,作为一般解决方案,它不是防弹的



回答by ceejayoz

Sure. Make a headers-only request and look for the Content-Lengthheader.

当然。发出仅标头请求并查找Content-Length标头。

回答by Sanchit Gupta

Php function get_headers()works for me to check the content-lengthas

Php 函数get_headers()适用于我检查内容长度

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

For More Detail : PHP Function get_headers()

更多细节:PHP 函数 get_headers()

回答by Jake

I'm not sure, but couldn't you use the get_headers function for this?

我不确定,但是您不能为此使用 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;

回答by Jake

one line best solution :

一行最佳解决方案:

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

php is too delicius

php 太美味了

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

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

回答by mpyw

The simplest and most efficient implementation:

最简单有效的实现:

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

回答by Rahul Kaushik

Try the below function to get Remote file size

尝试使用以下功能获取远程文件大小

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

回答by dkamins

Since this question is already tagged "php" and "curl", I'm assuming you know how to use Curl in PHP.

由于这个问题已经被标记为“php”和“curl”,我假设您知道如何在 PHP 中使用 Curl。

If you set curl_setopt(CURLOPT_NOBODY, TRUE)then you will make a HEAD request and can probably check the "Content-Length" header of the response, which will be only headers.

如果您设置,curl_setopt(CURLOPT_NOBODY, TRUE)那么您将发出 HEAD 请求,并且可能会检查响应的“Content-Length”标头,这将只是标头。