Cómo descargar un archivo desde una URL en Java

¿Está buscando crear su propio conjunto de datos para una aplicación nueva e innovadora? O tal vez esté tratando de recopilar datos para analizarlos para un proyecto universitario...

¿Está buscando crear su propio conjunto de datos para una aplicación nueva e innovadora? O tal vez está tratando de recopilar datos para analizarlos en un proyecto universitario y se ha cansado de descargar manualmente cada imagen o CSV. No se preocupe, en este artículo explicaré los componentes básicos necesarios para automatizar la descarga de archivos para este tipo de tareas.

Antes de que pueda crear una aplicación para descargar y crear conjuntos de datos para usted, deberá conocer los conceptos básicos necesarios para automatizar las descargas de archivos a través del código Java. Tener los conceptos básicos correctos lo ayudará a usarlos para su propio conjunto específico de necesidades, ya sea para una aplicación de servidor back-end o una aplicación de Android.

Hay varias formas de descargar un archivo usando código Java. Aquí hay algunas maneras de cómo puede realizar la tarea:

E/S de Java

El paquete básico y más fácilmente disponible para descargar un archivo de Internet usando código Java es el paquete E/S de Java. Aquí usaremos las clases BufferedInputStream y URL para abrir y leer un archivo en una dirección dada a un archivo en nuestro sistema local. La razón por la que usamos la clase BufferedInputStream en lugar de InputStream es su capacidad de almacenamiento en búfer que le da a nuestro código un impulso de rendimiento.

Antes de profundizar en el aspecto de la codificación, echemos un vistazo a las clases y las funciones individuales que usaremos en el proceso.

La clase java.net.URL en Java es una biblioteca integrada que ofrece múltiples métodos para acceder y manipular datos en Internet. En este caso, usaremos la función openStream() de la clase URL. La firma del método para la función openStream() es:

1
public final InputStream openStream() throws IOException

La función openStream() funciona en un objeto de la clase URL. La clase URL abre una conexión a la URL dada y el método openStream() devuelve un flujo de entrada que se usa para leer datos de la conexión.

La segunda clase que usaremos es BufferedInputStreamReader y FileOutputStream. Estas clases se utilizan para leer de un archivo y escribir en él, respectivamente.

Aquí está el código completo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
try (BufferedInputStream inputStream = new BufferedInputStream(new URL("http://example.com/my-file-path.txt").openStream());
  FileOutputStream fileOS = new FileOutputStream("/Users/username/Documents/file_name.txt")) {
    byte data[] = new byte[1024];
    int byteContent;
    while ((byteContent = inputStream.read(data, 0, 1024)) != -1) {
        fileOS.write(data, 0, byteContent);
    }
} catch (IOException e) {
    // handles IO exceptions
}

Nota: es posible que deba agregar el encabezado 'User-Agent' a la solicitud HTTP, ya que algunos servidores no permiten descargas de clientes desconocidos.

Como puede ver, abrimos una conexión usando el objeto URL y luego la leemos a través del objeto BufferedInputStreamReader. Los contenidos se leen como bytes y se copian a un archivo en el directorio local usando FileOutputStream.

Para reducir el número de líneas de código, podemos usar la clase Files disponible en Java 7. La clase Files contiene métodos que leen todos los bytes a la vez y luego los copian en otro archivo. Así es como puedes usarlo:

1
2
InputStream inputStream = new URL("http://example.com/my-file-path.txt").openStream();
Files.copy(inputStream, Paths.get("/Users/username/Documents/file_name.txt"), StandardCopyOption.REPLACE_EXISTING);

Java NIO

Java NIO es un paquete alternativo para manejar operaciones de red y de entrada y salida en Java. La principal ventaja que ofrece el paquete NIO de Java es que no bloquea y tiene capacidades de canalización y almacenamiento en búfer. . Cuando usamos la biblioteca Java IO, trabajamos con flujos que leen datos byte a byte. Sin embargo, el paquete Java NIO usa canales y búferes. Las capacidades de almacenamiento en búfer y canalización permiten que el sistema copie el contenido de una URL directamente al archivo deseado sin necesidad de guardar los bytes en la memoria de la aplicación, lo que sería un paso intermedio. La capacidad de trabajar con canales aumenta el rendimiento.

Para descargar el contenido de una URL, utilizaremos las clases ReadableByteChannel y FileChannel.

1
ReadableByteChannel readChannel = Channels.newChannel(new URL("http://example.com/my-file-path.txt").openStream());

La clase ReadableByteChannel crea una secuencia para leer el contenido de la URL. Los contenidos descargados se transferirán a un archivo en el sistema local a través del canal de archivos correspondiente.

1
2
FileOutputStream fileOS = new FileOutputStream("/Users/username/Documents/file_name.txt");
FileChannel writeChannel = fileOS.getChannel();

Después de definir el canal del archivo, usaremos el método transferFrom() para copiar los contenidos leídos desde el objeto readChannel al destino del archivo usando el objeto writeChannel.

1
2
writeChannel
  .transferFrom(readChannel, 0, Long.MAX_VALUE);

Los métodos transferFrom() y transferTo() son mucho más eficientes que trabajar con flujos usando un búfer. Los métodos de transferencia nos permiten copiar directamente el contenido de la memoria caché del sistema de archivos en el archivo del sistema. Por lo tanto, la canalización directa restringe la cantidad de cambios de contexto necesarios y mejora el rendimiento general del código.

Ahora, en las siguientes secciones, buscaremos formas de descargar archivos desde una URL utilizando bibliotecas de terceros en lugar de los componentes básicos de la funcionalidad de Java.

Apache Commons E/S

La biblioteca Apache Commons E/S ofrece una lista de clases de utilidades para administrar las operaciones de IO. Ahora puede estar pensando por qué usaríamos esto cuando Java tiene su propio conjunto de bibliotecas para manejar las operaciones de IO. Sin embargo, Apache Commons IO supera el problema de la reescritura de código y ayuda a evitar escribir código repetitivo.

Para comenzar a utilizar la biblioteca Apache Commons IO, deberá descargar los archivos jar de la [página web oficial] (http://commons.apache.org/proper/commons-io/download_io.cgi). Cuando haya terminado de descargar los archivos jar, debe agregarlos para usarlos. Si utiliza un entorno de desarrollo integrado (IDE) como Eclipse, deberá agregue los archivos a la ruta de compilación de su proyecto. Para agregar archivos a su proyecto, debe hacer clic con el botón derecho en él, seleccionar la opción de ruta de compilación navegando a través de "configurar ruta de compilación-> ruta de compilación", y luego elegir la opción Agregar archivos externos.

Para descargar un archivo desde una URL determinada utilizando Apache Commons IO, necesitaremos la clase FileUtils del paquete. Solo se requiere una sola línea de código para descargar un archivo, que se ve así:

1
2
3
4
5
FileUtils.copyURLToFile(
  new URL("http://example.com/my-file-path.txt"), 
  new File("/Users/username/Documents/file_name.txt"), 
  CONNECTION_TIMEOUT, 
  READ_TIMEOUT);

Los tiempos de espera de conexión y lectura transmiten el tiempo permitido durante el cual la conexión puede permanecer inactiva o la lectura de la URL puede detenerse.

Otra clase del paquete Apache Commons IO que se puede usar para descargar un archivo a través de Internet es [IOUtils](https://commons.apache.org/proper/commons-io/javadocs/api-2.5/org/apache /commons/io/IOUtils.html#copy(java.io.InputStream,%20java.io.OutputStream)) clase. Usaremos el método copy(inputStream, fileOS) para descargar un archivo en el sistema local.

1
2
3
InputStream inputStream = new URL("http://example.com/my-file-path.txt").openStream();
FileOutputStream fileOS = new FileOutputStream("/Users/username/Documents/file_name.txt");
int i = IOUtils.copy(inpuStream, fileOS);

La función devuelve el número de bytes copiados. Si el valor de la variable i es -1, indica que el contenido del archivo supera los 2 GB. Cuando el valor devuelto es -1, puede usar la función copyLarge(inputStream, fileOS) en lugar de la función copy(inputstream, fileOS) para manejar esta carga. Ambas funciones amortiguan el inputstream internamente. El búfer interno significa que no tenemos que usar la clase BufferedInputStream para mejorar el rendimiento de nuestro código y nos ayuda a evitar escribir código repetitivo.

Uso de componentes HTTP de Apache {#uso de componentes http de Apache}

Otra biblioteca administrada por la organización Apache es el paquete HttpComponents. Esta biblioteca utiliza el mecanismo de solicitud y respuesta para descargar el archivo desde una URL determinada.

El primer paso para descargar un archivo es crear un objeto de cliente HTTP que emita la solicitud al servidor. Para esto, usaremos la clase CloseableHttpClient. La clase CloseableHttpClient es una clase abstracta que requiere la clase HttpClientBuilder para crear instancias. El fragmento de código que crea un nuevo cliente HTTP es el siguiente:

1
CloseableHttpClient client = HttpClientBuilder.create().build();

Luego necesitamos crear un objeto HttpGet o HttpPost para enviar la solicitud al servidor. La solicitud se crea mediante la siguiente línea de código:

1
HttpGet request = new HttpGet("url from where the file is intended to be downloaded");

La función ejecutar (solicitud) se aplica al objeto del cliente y regresa con una respuesta del servidor. Una vez que la solicitud se envía al servidor, necesitamos un objeto de respuesta para recibir los datos enviados desde el servidor. Para capturar la respuesta del servidor usamos el objeto de clase HttpResponse.

1
HttpResponse response = client.execute(request);

Los datos enviados por el servidor en forma de mensaje se obtienen a través de la función getEntity().

1
HttpEntity entity = response.getEntity();

También puede obtener el código de respuesta enviado por el servidor a través del objeto response y usarlo para sus necesidades específicas.

1
int responseCode = response.getStatusLine().getStatusCode();

Los datos que se descargarán se encapsulan dentro del objeto entidad y se pueden extraer utilizando la función getContent(). La función getContent() devuelve un objeto InputStream que se puede usar con un BufferedInputStreamReader para mejorar el rendimiento.

1
InputStream inputStream = entity.getContent();

Ahora todo lo que necesita hacer es leer el flujo byte por byte y escribir el contenido en un archivo usando la clase FileOutputStream.

1
2
3
4
5
6
String fileName = "D:\\Demo\file.txt";
FileOutputStream fos = new FileOutputStream(filename);
Int byte;
while((byte = inputStream.read()) != -1) {
    fos.write(byte);
}

Lo último que se debe hacer es cerrar todos los recursos abiertos para garantizar que los recursos del sistema no se utilicen en exceso y que no haya pérdidas de memoria.

Conclusión

Ahí lo tiene: estas son las formas más sencillas de descargar un archivo utilizando el código Java básico y otras bibliotecas de terceros. Ahora que hemos terminado con lo básico, puede ser tan creativo como desee y utilizar el conocimiento para satisfacer sus necesidades. Así que nos vemos la próxima vez con un nuevo conjunto de conceptos para ayudarlo a convertirse en un mejor programador. Le deseamos feliz codificación hasta entonces. es.

Licensed under CC BY-NC-SA 4.0