2008-11-04 10 views
27

Estoy trabajando en un proyecto para la escuela, y estoy implementando una herramienta que se puede utilizar para descargar archivos de la web (con una opción de aceleración). La cuestión es que tendré una GUI para ello y usaré un widget JProgressBar, que me gustaría mostrar el progreso actual de la descarga. Para eso necesitaría saber el tamaño del archivo. ¿Cómo se obtiene el tamaño del archivo antes de descargar el archivo?Java URLConnection: ¿cómo puedo averiguar el tamaño de un archivo web?

Respuesta

36

Cualquier respuesta HTTP es supone contener un encabezado Content-Length, por lo que podría consultar el objeto URLConnection para este valor.

//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... 
     ... 
    } 

No siempre podría ser posible que un servidor devuelva una precisa Content-Length, por lo que el valor podría ser inexacta, pero al menos se podrían obtener algunos valor utilizable mayor parte del tiempo.

actualización: O, ahora que miro el URLConnection javadoc más completamente, puede usar el método getContentLength().

+1

getContentLength() da enlace de página no encontrada, ver http://docs.oracle.com/javase/6/ docs/api/java/net/URLConnection.html # getContentLength() – Reg

+0

getContentLength no siempre devolverá un valor. Por ejemplo, cuando se realiza una solicitud que devuelve un resultado dinámico donde el tamaño del contenido no se conoce por adelantado. – coderama

4

Querrá utilizar la longitud del contenido (URLConnection.getContentLength()). Desafortunadamente, esto no siempre será preciso o no siempre se proporcionará, por lo que no siempre es seguro confiar en él.

32

Como se mencionó, URLConnection's getContentLength es su mejor opción, pero no siempre dará una longitud definida. Esto se debe a que el protocolo HTTP (y otros que podrían estar representados por una URLConnection) no siempre transmiten la longitud.

En el caso de HTTP, la longitud del contenido dinámico normalmente no se conoce de antemano — cuando normalmente se enviará el encabezado content-length. En cambio, otro encabezado, transfer-coding, especifica que se utiliza una codificación "fragmentada". Con la codificación fragmentada, la duración de toda la respuesta no se especifica, y la respuesta se envía de nuevo en pedazos, donde se especifica el tamaño de cada pieza. En la práctica, el servidor almacena la salida del servlet. Cada vez que el buffer se llena, se envía otro fragmento. Usando este mecanismo, HTTP podría comenzar a transmitir una respuesta de longitud infinita.

Otra razón por la que es posible que no pueda obtener la longitud de un archivo a través de URLConnection es si el archivo es más grande que 2 Gb, que es el límite para un entero positivo.

+2

+1 para la precisión. J2SE 1.4 devuelve -1 si lee la longitud del contenido en el objeto URLConnection para una respuesta fragmentada. Este no fue el caso en J2SE 1.3. –

0

Como dijo @erickson, a veces aparece el encabezado "Transferir-Codificación: fragmentado", en lugar de "Contenido-Longitud:" y, por supuesto, tiene un valor nulo para la longitud.

Acerca del método available() - nadie puede garantizarle que devolverá el valor correcto, por lo que le recomiendo que no lo use.

28

Utilizando una solicitud HEAD, recibí mi servidor web para que respondiera con el campo de longitud de contenido correcto que de lo contrario estaba vacío. No sé si esto funciona, en general, pero en mi caso lo hace:

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(); 
     } 
    } 
+1

Funciona muy bien para mí, muchas gracias. – z00l

1
//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

Por favor, publique una descripción encima del código explicando lo que hizo –

+0

Por favor edite con más información. Se desalientan las respuestas de solo código y "prueba esto", ya que no contienen contenido que se pueda buscar y no explican por qué alguien debe "probar esto". Hacemos un esfuerzo aquí para ser un recurso para el conocimiento. – abarisone

+0

Editado, lo terminé. –

Cuestiones relacionadas