Descarga de Archivos utilizando WebRequest y WebResponse Fecha: 30/Oct/2004 (28 Octubre 2004)
|
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.
Fichero con el c�digo de ejemplo: neo_mx_DescargaArchivos.zip - Tama�o 19 KB