Taille du fichier distant sans téléchargement de fichier

Est-il possible d’obtenir la taille d’un fichier distant http: //my_url/my_file.txt sans télécharger le fichier?

J’ai trouvé quelque chose à ce sujet ici :

Voici le meilleur moyen (que j’ai trouvé) pour obtenir la taille d’un fichier distant. Notez que les requêtes HEAD n’obtiennent pas le corps réel de la requête, elles récupèrent simplement les en-têtes. Faire une requête HEAD à une ressource de 100 Mo prendra donc autant de temps qu’une requête HEAD à une ressource de 1 Ko.

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

Essayez ce code

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

Comme mentionné à quelques resockets, la solution consiste à récupérer les informations du champ Content-Length tête de réponse .

Cependant, vous devriez noter que

  • le serveur que vous testez n’implémente pas nécessairement la méthode HEAD (!)
  • Il n’est absolument pas nécessaire de créer manuellement une requête HEAD (qui, encore une fois, ne serait peut-être même pas prise en charge) en utilisant fopen ou similaire ou même pour invoquer la bibliothèque curl, lorsque PHP a get_headers() (souvenez-vous: KISS )

L’utilisation de get_headers() suit le principe KISS et fonctionne même si le serveur que vous testez ne prend pas en charge la requête HEAD.

Alors, voici ma version (gimmick: retourne la taille formatée lisible par un humain ;-)):

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

  * @license MIT  * @url  * * @param ssortingng $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 ssortingng 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 resortingeve 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" 

Remarque supplémentaire: l'en -tête Content-Length est facultatif. Ainsi, en règle générale, ce n'est pas une preuve de balle !


Sûr. Effectuez une requête en en-têtes uniquement et recherchez l’en Content-Length tête Content-Length .

Je ne suis pas sûr, mais ne pourriez-vous pas utiliser la fonction get_headers pour cela?

 $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 fonction php get_headers() fonctionne pour que je vérifie la longueur du contenu

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

Pour plus de détails: Fonction PHP get_headers ()

La mise en œuvre la plus simple et la plus efficace:

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

Comme cette question est déjà marquée “php” et “curl”, je suppose que vous savez comment utiliser Curl en PHP.

Si vous définissez curl_setopt(CURLOPT_NOBODY, TRUE) vous ferez une requête HEAD et pourrez probablement vérifier l’en-tête “Content-Length” de la réponse, qui ne sera que des en-têtes.

Essayez la fonction ci-dessous pour obtenir la taille du fichier distant

 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 plupart des réponses utilisent soit CURL, soit des unités de lecture. Mais dans certaines situations, vous pouvez utiliser une solution beaucoup plus simple. Considérez la note sur les filesize() de filesize() sur PHP.net . Vous y trouverez une astuce disant: ” Depuis PHP 5.0.0, cette fonction peut également être utilisée avec certains wrappers d’URL. Reportez-vous à Protocoles et wrappers pris en charge pour déterminer quels wrappers prennent en charge la famille de fonctionnalités stat () “.

Donc, si votre serveur et votre parsingur PHP sont correctement configurés, vous pouvez simplement utiliser la fonction filesize() , l’employer avec l’URL complète, pointer vers un fichier distant, quelle taille vous voulez obtenir, et laisser PHP faire tout son possible.

Voici une autre approche qui fonctionnera avec les serveurs qui ne prennent pas en charge les demandes HEAD .

Il utilise cURL pour faire une demande pour le contenu avec un en-tête de plage HTTP demandant le premier octet du fichier.

Si le serveur prend en charge les demandes d’intervalle (la plupart des serveurs de médias le feront), il recevra la réponse avec la taille de la ressource.

Si le serveur ne répond pas avec une plage d’octets, il recherchera un en-tête de longueur de contenu pour déterminer la longueur.

Si la taille se trouve dans un en-tête de plage ou de longueur de contenu, le transfert est interrompu. Si la taille est introuvable et que la fonction commence à lire le corps de la réponse, le transfert est interrompu.

Cela pourrait être une approche supplémentaire si une requête HEAD entraîne une réponse non prise en charge par la méthode 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 (sortingm($line) == '') { $in_headers = false; } list($header, $content) = explode(':', $line, 2); $header = strtolower(sortingm($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; } 

Usage:

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

une ligne meilleure solution:

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

php est trop delicius

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

Essayez ceci: je l’utilise et j’ai un bon résultat.

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

Maintenant, testez comme ceci:

 echo getRemoteFilesize('http://soffr.miximages.com/php/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; 

Résultats:

24,82 KiB

912 KiB

101,85 KiB