Dimensione del file remoto senza scaricare il file

C’è un modo per ottenere la dimensione di un file remoto http: //my_url/my_file.txt senza scaricare il file?

Trovato qualcosa su questo qui :

Ecco il modo migliore (che ho trovato) per ottenere le dimensioni di un file remoto. Si noti che le richieste HEAD non ricevono il corpo reale della richiesta, ma recuperano semplicemente le intestazioni. Pertanto, l’esecuzione di una richiesta HEAD a una risorsa di 100 MB richiederà lo stesso tempo di una richiesta HEAD a una risorsa di 1 KB.

 300 && $status <= 308) ) { $result = $content_length; } } return $result; } ?> 

Uso:

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

Prova questo codice

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

Come accennato un paio di volte, la strada da percorrere è recuperare le informazioni dal campo Content-Length dell’intestazione di risposta .

Tuttavia, dovresti tenerlo presente

  • il server che stai sondando non implementa necessariamente il metodo HEAD (!)
  • non è assolutamente necessario creare manualmente una richiesta HEAD (che, di nuovo, potrebbe non essere nemmeno supportata) usando fopen o simili o anche per invocare la libreria fopen , quando PHP ha get_headers() (ricorda: KISS )

L’uso di get_headers() segue il principio KISS e funziona anche se il server che stai sondando non supporta la richiesta HEAD.

Quindi, ecco la mia versione (gimmick: restituisce le dimensioni in formato leggibile ;-)):

Gist: https://gist.github.com/eyecatchup/f26300ffd7e50a92bc4d (versione curl e get_headers)
get_headers () – Versione:

  * @license MIT  * @url  * * @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 } 

Uso:

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

Nota aggiuntiva: l'intestazione Content-Length è facoltativa. Quindi, come soluzione generale, non è a prova di proiettile !


Sicuro. Esegui una richiesta di solo intestazioni e cerca l’intestazione Content-Length .

Non sono sicuro, ma non potresti usare la funzione get_headers per questo?

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

La funzione PHP get_headers() funziona per me per controllare la lunghezza del contenuto come

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

Per maggiori dettagli: Funzione PHP get_headers ()

L’implementazione più semplice ed efficiente:

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

Dato che questa domanda è già taggata “php” e “curl”, presumo che tu sappia come usare Curl in PHP.

Se imposti curl_setopt(CURLOPT_NOBODY, TRUE) , eseguirai una richiesta HEAD e probabilmente potrai controllare l’intestazione “Content-Length” della risposta, che sarà solo le intestazioni.

Prova la funzione qui sotto per ottenere le dimensioni del file Remote

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

La maggior parte delle risposte qui utilizza CURL o si basa sulla lettura di intestazioni. Ma in alcune situazioni certe puoi usare una soluzione più semplice. Prendi nota dei documenti su filesize() su PHP.net . Troverai un suggerimento che dice: ” A partire da PHP 5.0.0, questa funzione può essere utilizzata anche con alcuni wrapper di URL. Fai riferimento a Protocolli e wrapper supportati per determinare quali wrapper supportano la famiglia di funzionalità stat () “.

Quindi, se il tuo server e il tuo parser PHP sono configurati correttamente, puoi semplicemente usare la funzione filesize() , alimentarla con l’URL completo, puntare a un file remoto, quale dimensione vuoi ottenere, e lasciare che PHP faccia il massimo.

Ecco un altro approccio che funzionerà con i server che non supportano le richieste HEAD .

Usa cURL per fare una richiesta per il contenuto con un header di intervallo HTTP che richiede il primo byte del file.

Se il server supporta richieste di intervallo (la maggior parte dei server multimediali lo farà), riceverà la risposta con la dimensione della risorsa.

Se il server non risponde con un intervallo di byte, cercherà un’intestazione di lunghezza del contenuto per determinare la lunghezza.

Se la dimensione viene trovata in un intervallo o intestazione di lunghezza del contenuto, il trasferimento viene interrotto. Se la dimensione non viene trovata e la funzione inizia a leggere il corpo della risposta, il trasferimento viene interrotto.

Questo potrebbe essere un approccio supplementare se una richiesta HEAD risulta in un metodo 405 non supportato.

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

Uso:

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

una soluzione migliore per una linea:

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

php è troppo costoso

 function urlsize($url):int{ return array_change_key_case(get_headers($url,1))['content-length']; } echo urlsize("http://.../file.txt"); 

Prova questo: lo uso e ho ottenuto un buon risultato.

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

Ora, prova come questi:

 echo getRemoteFilesize('http://sofit.miximages.com/curl/suspendedpage.cgi').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; 

risultati:

24,82 KiB

912 KiB

101,85 KiB