web-dev-qa-db-fra.com

Java URLConnection: comment connaître la taille d'un fichier Web?

Je travaille sur un projet pour l'école et j'implémente un outil qui peut être utilisé pour télécharger des fichiers depuis le web (avec une option de limitation). Le truc, c'est que je vais avoir une interface graphique pour cela, et j'utiliserai un widget JProgressBar, que je voudrais montrer la progression actuelle du téléchargement. Pour cela, j'aurais besoin de connaître la taille du fichier. Comment obtenez-vous la taille du fichier avant de télécharger le fichier.

30
Geo

Toute réponse HTTP est supposée pour contenir un en-tête Content-Length, vous pouvez donc interroger l'objet URLConnection pour cette valeur.

//once the connection has been opened
List values = urlConnection.getHeaderFields().get("content-Length")
if (values != null && !values.isEmpty()) {

    // getHeaderFields() returns a Map with key=(String) header 
    // name, value = List of String values for that header field. 
    // just use the first value here.
    String sLength = (String) values.get(0);

    if (sLength != null) {
       //parse the length into an integer...
       ...
    }

Il n'est pas toujours possible pour un serveur de renvoyer une Content-Length précise, donc la valeur peut être inexacte, mais au moins vous obtiendrez certains la valeur utilisable la plupart du temps.

mise à jour: Ou, maintenant que je regarde le javadoc URLConnection plus complètement, vous pouvez simplement utiliser la méthode getContentLength () .

38
matt b

Comme mentionné, URLConnection's getContentLengthLong() est votre meilleur pari, mais il ne donnera pas toujours une longueur définie. C'est parce que le protocole HTTP (et d'autres qui pourraient être représentés par un URLConnection) ne transmet pas toujours la longueur.

Dans le cas de HTTP, la longueur du contenu dynamique n'est généralement pas connue à l'avance, lorsque l'en-tête content-length Est normalement envoyé. Au lieu de cela, un autre en-tête, transfer-encoding, Spécifie qu'un codage "fragmenté" est utilisé. Avec un codage en morceaux, la longueur de la réponse entière n'est pas spécifiée et la réponse est renvoyée en morceaux, où la taille de chaque morceau est spécifiée. En pratique, les tampons du serveur sortent de la servlet. Chaque fois que le tampon se remplit, un autre morceau est envoyé. En utilisant ce mécanisme, HTTP pourrait réellement commencer à diffuser une réponse de longueur infinie.

Si un fichier est plus grand que 2 Go, sa taille ne peut pas être représentée par un int, donc l'ancienne méthode, getContentLength() renverra -1 dans ce Cas.

33
erickson

En utilisant une demande HEAD, j'ai demandé à mon serveur Web de répondre avec le champ de longueur de contenu correct qui, sinon, était vide. Je ne sais pas si cela fonctionne en général, mais dans mon cas, c'est le cas:

    private int tryGetFileSize(URL url) {
        HttpURLConnection conn = null;
        try {
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("HEAD");
            conn.getInputStream();
            return conn.getContentLength();
        } catch (IOException e) {
            return -1;
        } finally {
            conn.disconnect();
        }
    }
28
betty

Vous souhaiterez utiliser la longueur du contenu (URLConnection.getContentLength ()). Malheureusement, cela ne sera pas toujours exact ou ne sera pas toujours fourni, il n'est donc pas toujours sûr de s'y fier.

4
Herms
    //URLConnection connection

private int FileSize(String url) {

 // this is the method and it get the url as a parameter.

       // this Java class will allow us to get the size of the file.

        URLConnection con; 

         // its in a try and catch incase the url given is wrong or invalid

        try{ 

            // we open the stream

            con = new URL(url).openConnection()

            return con.getContentLength(); 
        }catch (Exception e){

            e.printStackTrace();

            // this is returned if the connection went invalid or failed.

            return 0; 
        }
    }
1
Abdul Sheikh

Comme l'a dit @erickson, il y a parfois un en-tête "Transfer-Encoding: chunked", au lieu de "Content-Length:" et bien sûr, vous avez une valeur nulle pour la longueur.

À propos de la méthode available () - personne ne peut vous garantir qu'elle renverra la valeur appropriée, je vous recommande donc de ne pas l'utiliser.

0
Petromir Dzhunev