Descarga de Archivos utilizando WebRequest y WebResponse

Fecha: 30/Oct/2004 (28 Octubre 2004)
Autor: Misael Monterroca mmonterroca@neo-mx.com

 


 

Contenido

Introducción

Creando las Clases

Desmenuzando las clases

Llamando el componente

Conclusión

Introducción

Día con día las aplicaciones apuntan hacía la revolución que sigue siendo Internet, esto nos ha llevado a utilizar este recurso como una funcionalidad ya sea para descargar actualizaciones, sincronizar información, actualización de catálogos etc. Aun cuando esto lo podemos lograr utilizando por ejemplo WebServices no siempre la implementación de estas tecnologías depende completamente de nosotros obligándonos a utilizar otro medio de interacción para lograr la funcionalidad requerida.

.Net Framework nos proporciona clases para poder trabajar con recursos de red

System.Net el cual nos proporciona clases que encapsulan la funcionalidad de la mayoría de los protocolos y servicios que actualmente se manejan en Internet http, ftp, dns, autenticación etc.

System.Net.Sockets que es una implementación de los sockets de windows, pero a diferencia  System.Net este no proporciona ninguna clase directa para el manejo de los protocolos actuales (http,ftp.https), con lo cual toda la interacción con ellos deberá ser programada completamente.

Del espacio de nombres System.Net  se desprenden las clases WebRequest y WebResponse las cuales proporcionan la funcionalidad necesaria para conectarse  y obtener información común de la mayoría de los protocolos  conectables (http, https, ftp) , si se necesitará obtener información especifica de un determinado protocolo se pueden utilizar sus clases derivadas como HttpWebRequest la cual administra los detalles de una conexión http (propiedades del tipo Refer  o Host por ejemplo)

 

Creando las Clases

Para la realización de nuestro componente utilizaremos 4 clases:

DescargaArchivo Será el punto de entrada de nuestra componente, la cual expondrá todas las propiedades y métodos necesarios para realizar la descarga de un archivo vía HTTP

Autentificación Proporciona  la clase NetworkCredentials que nos permitirá enviar las credenciales correspondientes del usuario en caso de que el usuario necesite estar autentificado.

Proxy Proporciona la clase WebProxy la cual es necesaria en caso de tener salida a la red a través de un Proxy.

ProgresoEventArgs Proporciona los argumentos que contendrá el evento Progreso, el cual nos indicara el numero de bytes  que se han sido descargados

Desmenuzando las clases

Declaración del método principal

    

public void Descargar()

            {

            try

            {

//Igualo las propiedades al valor original por si no han sido inicializadas y originen su propio error.

            this.direccionArchivo = this.direccionArchivo;

            this.guardarEn = this.guardarEn;

                   

 

La clase WebRequest es la encargada de procesar la solicitud del recurso, dado que es una clase abstracta se debe de utilizar el método “Create(uri)” para poder crear una instancia. En nuestro caso el URI es la dirección de Internet del archivo a descargar.

 

//Se inicializa la petición

WebRequest WRPeticion = WebRequest.Create(_direccionArchivo);

 

 

Antes de realizar la solicitud al recurso, es posible que se tenga que configurar la autentificación del servidor al cual se esta realizando la petición. También de igual manera  puede ser necesario realizar la configuración de un  Proxy en caso de que la aplicación necesite utilizar alguno para acceder a Internet.

 

 

En esta sección de código se verifica si es necesario utilizar un Proxy.

 

//Asigna el proxy

if (this.requiereProxy)

{                            

      WRPeticion.Proxy = _Proxy.WebProxy;

                             

}

 

En caso de que la propiedad “RequiereProxy” sea verdadera, con anterioridad debió inicializar la propiedad “WebProxy” que a su vez regresa  una instancia de nuestra clase Proxy mediante la cual se crea la clase WebProxy correspondiente

 

public Proxy WebProxy()

{

      return _Proxy;

}

 

La única propiedad requerida de la  clase WebProxy es “Direccion” la cual debe  ser una dirección URI valida (“http://www.neo-mx.com”), la comprobación se puede realizar utilizando la clase URI la cual será asignada a la propiedad  “Address” de la clase “WebProxy”

 

public class Proxy

{

WebProxy _proxy;

string _direccion = "";

string _password = "";

string _usuario = "";

 

public Proxy(){_proxy = new WebProxy();} 

 

public WebProxy WebProxy

{

      get

      {

            try

            {

                  this.Direccion = this.Direccion;

 

                  _proxy.Address = new Uri(this.Direccion);

 

 

En caso de que nuestro Proxy necesite autentificación es necesario utilizar la clase NetworkCredential, especificando un usuario y un password en las propiedades correspondientes de la clase Proxy (Proxy.Usuario, Proxy.Password) aunque este último puede ser una cadena vacía

 

 

if (_usuario != "")

{

 _proxy.Credentials = new NetworkCredential(_usuario,_password);

}

                  }

 

En caso de que el recurso al cual queremos acceder necesite autentificación entonces el procedimiento será similar.

 

 

//Asigna las credenciales

if (this.requiereAutentificacion)

{

WRPeticion.Credentials = _Autentificacion.networkCredential;

                        }

 

 

La diferencia es que en este caso la clase que es instanciada es “Autentificación” a través de la propiedad “WebAutentificacion”

 

public Autentificacion WebAutentificacion()

{

      return _Autentificacion;

}

 

La clase “Autentificacion”  crea una clase NetworkCredentials

 

      public NetworkCredential networkCredential

            {

                  get

                  {

                        try

                        {

                              this.Usuario = this.Usuario;

                              return new NetworkCredential(this.Usuario,this.Password);

                        }

                        catch(Exception ex)

                        {

                              throw new Exception(ex.Message,ex);

                        }

                  }

            }

 

 

Ya que nuestra clase “WebRequest” ha sido configurada correctamente se realiza la solicitud al servidor utilizando el método “GetResponse”, este método contiene la respuesta de la solicitud del recurso la cual tiene que ser asignado a una clase WebResponse la cual será la encargada de obtener la secuencia de información correspondiente.

 

//Obtengo la respuesta

WebResponse WRRespuesta = WRPeticion.GetResponse();  

 

 

 

Dependiendo del tipo de archivo seleccionado basándose en la enumeración “eTipoArchivo” (Binario o Texto) se guardara la información pero utilizando su secuencia correspondiente

 

      //Dependiendo del tipo de archivo se llama a la función

if (this.tipoArchivo == (int)eTipoArchivo.Binario)

{

      this.archivoBinario(ref WRRespuesta);

}

else

{

      this.archivoTexto(ref WRRespuesta);

}

 

Si el tipo de archivo seleccionado es Binario, entonces llamaremos al método “archivoBinario” al cual se le pasa como parámetro el objeto WebResponse creado con anterioridad, se obtiene el tamaño del archivo a través de la propiedad  ContentLength, el cual posteriormente se enviara como parte de los argumentos del evento “Progreso”

Se crea una matriz de 1024 bytes, dentro del cual se ira almacenando de manera progresiva la respuesta de la secuencia de información recibida de la clase WebResponse

 

 

private void archivoBinario(ref WebResponse WRRespuesta)

            {

                  try

                  {

                        long tamañoArchivo = WRRespuesta.ContentLength;

                        byte[] Buffer = new byte[1024];

                        int intBytesLeidos = 0;

                                                _bitesRecibidos = 0;

 

Debido a que la secuencia a recibir será binaria, se crean dos clases BinaryReader y BinaryWriter.

BinaryReader será la encargada de obtener la secuencia de datos, esta es  obtenida a través del método “GetResponseStream” de la clase WebResponse

BinaryWriter por su parte, guardara la secuencia obtenida del BinaryReader en un archivo especificado utilizando la clase  FileStream, la ruta del archivo a guardar la tomara de la propiedad “guardarEn”,

BinaryReader BRRespuesta = new BinaryReader(WRRespuesta.GetResponseStream());

BinaryWriter BWEscritorBin = new BinaryWriter(new FileStream(this.guardarEn,FileMode.Create,FileAccess.Write,FileShare.None));

 

 

Se invocara al método “Read” de la clase BinaryReader, este método lee de la secuencia y el resultado lo almacenara en el buffer de bytes previamente definido,  el resultado será el numero de bytes leídos de la secuencia.

Si el número de bytes leídos es mayor a cero, entonces se guardara la secuencia guardada en el buffer, para esto se utiliza la propiedad “Write” de la clase BinaryWriter.

Una vez que es guardada la secuencia del buffer se invoca al evento “Progreso”, este evento envía la clase  ProgresoEventArgs,  la cual contiene la definición de los argumentos del evento que son el número de bytes recibidos hasta el momento y el número total de bytes del archivo.

Este proceso es repetido hasta que se lee por completo la secuencia desde el BinaryReader

 

intBytesLeidos = BRRespuesta.Read(Buffer,0,1024);                                        

 

while  (intBytesLeidos > 0 != this.cancelaDescarga)

{

      //Guardo la información en el archivo

      BWEscritorBin.Write(Buffer,0,intBytesLeidos);

     

      _bitesRecibidos += intBytesLeidos;

      ProgresoEventArgs e = new ProgresoEventArgs(_bitesRecibidos,tamañoArchivo);                      

      OnProgreso(e);   

      intBytesLeidos = BRRespuesta.Read(Buffer,0,1024);                                                          

}                                              

 

BWEscritorBin.Close();        //Cerramos la conexión

 

 

 

Llamando al componente

El código de ejemplo incluye un proyecto mediante el cual es utilizado el componente creado.

 

Este cliente utiliza toda la funcionalidad de la clase DescargaArchivo

Si quiere conocer el proceso de descarga es necesario ligar el evento “Progreso” , con el cual podríamos por ejemplo crear una barra de progreso que nos indique el porcentaje de descarga del archivo.

 

private void btnDescargar_Click(object sender, System.EventArgs e)

            {

                  try

                  {

                        objDescarga.tipoArchivo = (int) cboTipoArchivo.SelectedIndex;                  

                        objDescarga.Progreso += new ProgresoEventHandler(objDescarga_Progreso);                      

                        objDescarga.Descargar();                       

                        MessageBox.Show("Terminado","Información del sistema",MessageBoxButtons.OK,MessageBoxIcon.Information);                                                                   

 

                  }                

 

 

private void objDescarga_Progreso(object sender, ProgresoEventArgs e)

            {

                  try

                  {

                        PBProgreso.Maximum = (int) e.BytesTotales;

                        PBProgreso.Value = (int) e.BytesRecibidos;                       

                  }

 

Conclusión

La clases WebRequest y WebResponse representan un poderoso mecanismo de comunicación con la mayoría de los protocolos conectables (HTTP,HTTPS,FTP),

Aunque para la descarga de archivos existe la clase WebClient esta de igual manera utiliza la clase  WebRequest para acceder al recurso solicitado, la descarga de archivos no es el único fin que tienen estas clases ya que pueden ser útiles en varias circunstancias como la sincronización de información entre servidores Web, acceso a servidores Ftp, descarga de paginas Web etc.


 


ir al índice

Fichero con el código de ejemplo: neo_mx_DescargaArchivos.zip - Tamaño 19 KB