96 votes

Taille du fichier à distance sans téléchargement du fichier

Existe-t-il un moyen d'obtenir la taille d'un fichier distant ? http://my_url/my_file.txt sans télécharger le fichier ?

111voto

NebuSoft Points 2408

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

Voici la meilleure façon (que j'ai trouvée) d'obtenir la taille d'un fichier distant distant. Notez que les requêtes HEAD ne récupèrent pas le corps de la requête, elles récupèrent juste les en-têtes. Ainsi, faire une requête HEAD vers une ressource qui fait 100 Mo prendra le même temps qu'une requête HEAD vers une ressource de ressource qui fait 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;
}
?>

Utilisation :

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

0 votes

J'ai lu ça tout à l'heure, je ne savais pas si content-length signifiait la longueur ou la taille du fichier

0 votes

Si la requête renvoie un fichier, la taille de la requête est la taille du fichier

5 votes

Mais gardez à l'esprit qu'il y a peut être des réponses sans Content-length.

69voto

macki Points 440

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

0 votes

Si cela ne fonctionne pas pour vous, vous pouvez ajouter curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); .

3 votes

Cela ne fonctionne pas pour moi pour une image. J'ai CURLOPT_FOLLOWLOCATION défini à true.

5 votes

@Abenil ajoute ce paramètre. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false) ;

32voto

eyecatchUp Points 3091

Comme il a été mentionné à plusieurs reprises, la solution consiste à récupérer les informations de l'en-tête de réponse Content-Length champ .

Cependant, vous devez noter que

  • le serveur que vous sondez 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 (ce qui, encore une fois, n'est peut-être même pas pris en charge) en utilisant fopen ou similaire ou même pour invoquer la bibliothèque curl, alors que PHP a get_headers() (Souvenez-vous : K.I.S.S. )

Utilisation de get_headers() suit le Le principe K.I.S.S. et fonctionne même si le serveur que vous sondez ne prend pas en charge la requête HEAD.

Donc, voici ma version (gimmick : renvoie une taille formatée lisible par l'homme ;-)) :

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

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

Utilisation :

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

Note supplémentaire : L'en-tête Content-Length est facultatif. Ainsi, comme solution générale il n'est pas à l'épreuve des balles !


2 votes

Cela devrait être la réponse acceptée. Vrai, Content-Length est facultatif, mais c'est le seul moyen d'obtenir la taille du fichier sans le télécharger. get_headers est le meilleur moyen d'obtenir content-length .

2 votes

Sachez que cela changera la préférence de la méthode de requête en HEAD dans toutes les requêtes HTTP suivantes pour ce processus PHP. Utilisez stream_context_create pour créer un contexte séparé à utiliser pour l'appel à get_headers (7.1+).

0 votes

J'ajoute simplement que si votre URL ou le nom de votre fichier DOCUMENT contient des espaces, le résultat sera -1.

15voto

ceejayoz Points 85962

Bien sûr. Faites une demande d'en-tête seulement et cherchez l'élément Content-Length en-tête.

2voto

dkamins Points 10565

Puisque cette question est déjà étiqueté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 alors une demande HEAD et pourrez probablement vérifier l'en-tête "Content-Length" de la réponse, qui ne sera constituée que d'en-têtes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X