Is there a way to get the size of a remote file http://my_url/my_file.txt without downloading the file?
Most answers here uses either CURL or are basing on reading headers. But in some certain situations you can use a way easier solution. Consider note on filesize()'s docs on PHP.net. You'll find there a tip saying: "As of PHP 5.0.0, this function can also be used with some URL wrappers. Refer to Supported Protocols and Wrappers to determine which wrappers support stat() family of functionality".
So, if your server and PHP parser is properly configured, you can simply use filesize()
function, fed it with full URL, pointing to a remote file, which size you want to get, and let PHP do the all magic.
Since this question is already tagged "php" and "curl", I'm assuming you know how to use Curl in PHP.
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.
Sure. Make a headers-only request and look for the Content-Length
header.
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;
}
I'm not sure, but couldn't you use the get_headers function for this?
$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;
To cover the HTTP/2 request, the function provided here https://stackoverflow.com/a/2602624/2380767 needs to be changed a bit:
<?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];
} elseif( preg_match( "/^HTTP\/2 (\d\d\d)/", $data, $matches ) ) {
$status = (int)$matches[1];
}
if( preg_match( "/Content-Length: (\d+)/", $data, $matches ) ) {
$content_length = (int)$matches[1];
} elseif( 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;
}
?>