远程文件大小,无需下载文件

das*_*uki 78 php curl

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

Neb*_*oft 96

发现了一些关于这个在这里:

这是获得远程文件大小的最佳方式(我发现).请注意,HEAD请求不会获取请求的实际主体,它们只是检索标头.因此,对100MB的资源发出HEAD请求将花费与HEAD请求相同的时间量到1KB的资源.

<?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;
}
?>
Run Code Online (Sandbox Code Playgroud)

用法:

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

  • 这对我来说不起作用,因为没有定义`get_user_agent_string()`.删除整行使整个过程发挥作用. (9认同)
  • 像@macki建议的那样使用`curl_getinfo`不是更好吗? (4认同)
  • 但请记住,_can_是没有Content-length的响应. (3认同)
  • 如果服务器不支持 HEAD,则返回 405 (2认同)
  • 就像@Rapti一样,我收到了“get_user_agent_string()”的错误消息,这可能是代码中遗漏的本地函数。当行被注释掉时它可以工作,但也许可以使用`$_SERVER['HTTP_USER_AGENT']`代替函数 (2认同)

mac*_*cki 62

试试这个代码

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;
}
Run Code Online (Sandbox Code Playgroud)

  • @Abenil添加此参数.curl_setopt($ curl,CURLOPT_SSL_VERIFYPEER,false); (5认同)
  • 对于我尝试过的网址,它总是返回-1. (4认同)
  • 对我来说对于图像不起作用.我确实将`CURLOPT_FOLLOWLOCATION`设置为true. (3认同)

eye*_*hUp 31

如前所述,要走的路是从响应头的Content-Length字段中检索信息.

但是,你应该注意到

  • 您正在探测的服务器不一定实现HEAD方法(!)
  • fopen当PHP具有get_headers()(记住:KISS)时,绝对不需要手动制作HEAD请求(甚至可能甚至不支持)使用或类似甚至调用curl库

使用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
}
Run Code Online (Sandbox Code Playgroud)

用法:

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

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


  • 这应该是公认的答案.没错,`Content-Length`是可选的,但它是获取文件大小而不下载它的唯一方法 - 而`get_headers`是获得`content-length`的最佳方式. (2认同)
  • 请注意,这将在此 PHP 进程的所有后续 HTTP 请求中将请求方法的首选项更改为 HEAD。使用 `stream_context_create` 创建一个单独的上下文,用于调用 `get_headers` (7.1+)。 (2认同)

cee*_*yoz 13

当然.制作仅限标头的请求并查找Content-Length标头.


San*_*pta 10

PHP函数get_headers()工作对我来说,检查内容长度

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

详细信息:PHP函数get_headers()

  • 对于我(使用nginx),标题为Content-Length (4认同)

Jak*_*ake 7

我不确定,但你不能使用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;
Run Code Online (Sandbox Code Playgroud)


小智 6

一行最佳解决方案:

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

php 太美味了

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

echo urlsize("http://.../file.txt");
Run Code Online (Sandbox Code Playgroud)