Una funcionalidad básica que podemos encontrar en muchas aplicaciones para guardar y consultar archivos o simplemente para actualizarla es la carga de archivos al servidor. Hacerlo es realmente muy sencillo si encontramos la forma adecuada de hacerlo. Una mención importante es que utilizaremos al igual que muchísimos tutoriales un manejador genérico que tiene la extensión .ashx, la diferencia es que prácticamente ninguno te explica como poder hacerlo de modo productivo, así que primero debemos comenzar por establecer nuestro ambiente.
Para comenzar dirígete a la carpeta de tu servidor web IIS (C:\inetpub\wwwroot) y crea ahí una nueva carpeta, con el nombre que desees, después ve a la administración de tu sistema (Presiona Win+R y escribe compmgmt.msc), en el explorador de tu IIS, deberás poder ver la carpeta que acabas de crear.
Da clic derecho sobre ella y selecciona “Convertir en aplicación”.
Al hacer esto, el ícono de tu carpeta habrá cambiado de modo que te indica que ya tienes una aplicación web disponible.
Ahora vamos a crear la solución cliente que será la que el usuario vea y para hacerlo, deberemos comenzar por crear una aplicación Silverlight, ya con la solución recién creada agrega una carpeta en el proyecto de tu sitio web, de la siguiente forma.
En el folder de recursos, da clic derecho y en selecciona “Add a new item”, en el cuadro de diálogo que aparece escoge un manejador genérico.
Al momento de crear el manejador, deberás ver una pantalla similar a esta.
Y aquí inserta el siguiente código.
[sourcecode lang=’csharp’]<%@ WebHandler Language="C#" Class="Manejador" %>
using System;
using System.Web;
using System.IO;
public class Receptor : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string nombreArchivo = context.Request.QueryString[«nombreArchivo»].ToString();
using (FileStream stream = File.Create(context.Server.MapPath(«~/Datos/» + nombreArchivo)))
{
GuardarArchivo(context.Request.InputStream, stream);
}
}
private void GuardarArchivo(Stream stream, FileStream streamArchivo)
{
byte[] buffer = new byte[4096];
int bytesLeidos;
while ((bytesLeidos = stream.Read(buffer, 0, buffer.Length)) !=0)
{
streamArchivo.Write(buffer, 0, bytesLeidos);
}
}
public bool IsReusable
{
get { return false; }
}
}[/sourcecode]
El manejador genérico te permite poder ejecutar tareas complementarias de tipo ASP, en este caso por medio de la clase tienes dos métodos y una propiedad creados, el primer método es público y es el que mas adelante utilizarás desde tu cliente, el segundo método es privado y te sirve de apoyo para el primero, lo que hace es descomponer el archivo recibido en bytes y darles la secuencia correcta para “rearmar” tu archivo en el servidor. Por último una propiedad booleana, en este caso no la utilizarás para nada, pero es necesaria por el tipo de clase manejada, así que no la puedes eliminar.
Compila tu aplicación y con el menú contextual en el proyecto de inicio, usa el explorador de Windows para ver los archivos de tu proyecto. Y ya desde el explorador, copia el archivo que acabas de crear en la carpeta que ya tienes en tu IIS, además en la misma carpeta, crea un folder que se llame Datos.
Si tienes curiosidad en como se puede ver tu aplicación web en el explorador te toparás con un error, el cual para nuestros fines esta bien, dado que te estará indicando que necesita un parámetro por recibir.
Ya con toda esta configuración, regresa a tu solución Silverlight y en esta solución, en tu XAML, crea una interfaz que te quede de la siguiente forma.
[sourcecode lang=’xml’]
[/sourcecode]
Como puedes ver solo estas usando tres simples controles, un TextBox que te permitirá ver el nombre del archivo, un botón que tiene un manejador para su evento Clic y por último un TextBlock que te avisará que el archivo ha sido cargado satisfactoriamente. Ahora ve a tu code behind y coloca en el evento clic lo siguiente.
[sourcecode lang=’csharp’]private void btnSubir_Click(object sender, System.Windows.RoutedEventArgs e)
{
OpenFileDialog dialogo = new OpenFileDialog();
dialogo.Multiselect = false;
if (dialogo.ShowDialog() == true)
{
try
{
txtNombreArchivo.Text = dialogo.File.Name;
SubirArchivo(txtNombreArchivo.Text, dialogo.File.OpenRead());
}
catch (Exception ex)
{
MessageBox.Show(«Error: » + ex.Message);
}
}
}[/sourcecode]
Utilizando la clase OpenFileDialog vas a obtener el stream del archivo que quieres subir, así como su nombre, el segundo se irá al TextBox de la interfaz y ambos se irán al método SubirArchivo.
[sourcecode lang=’csharp’]private void SubirArchivo(string nombreArchivo, Stream datos)
{
UriBuilder constructor = new UriBuilder(«http://localhost/Recursos/Manejador.ashx»);
constructor.Query = string.Format(«nombreArchivo={0}», nombreArchivo);
WebClient cliente = new WebClient();
cliente.OpenWriteCompleted += (sender, e) =>
{
SubirInformacion(datos, e.Result);
e.Result.Close();
datos.Close();
};
cliente.OpenWriteAsync(constructor.Uri);
txtMensaje.Visibility = System.Windows.Visibility.Visible;
}[/sourcecode]
Este método es el conector de tus datos con el archivo de recursos que creaste al inicio, en donde por medio de un WebClient se enlazará y pasará el parámetro que solicita nuestro manejador, así como que al establecer conexión le enviará los datos, para ello necesitas un método mas llamado SubirInformación(), al final solo desplegará un mensaje de texto que te indica que todo salió bien.
[sourcecode lang=’csharp’]private void SubirInformacion(Stream entrada, Stream salida)
{
byte[] buffer = new byte[4096];
int bytesLeidos;
while ((bytesLeidos = entrada.Read(buffer, 0, buffer.Length)) != 0)
{
salida.Write(buffer, 0, bytesLeidos);
}
}[/sourcecode]
Este método al final lo que hace es descomponer la información del archivo en bytes de la forma adecuada por medio de un arreglo de bytes y un ciclo.
Así finalmente si todo esta correctamente realizado, podrás ejecutar tu aplicación, abrir una ventana de búsqueda de archivos, seleccionar uno y automáticamente aparecerá en tu carpeta de datos, para mostrar la navegación te dejo el siguiente video que te explica de mejor forma la funcionalidad.
Puedes descargar aquí el código ejemplo.
Estoy intentando realizar tu ejemplo me parece muy bueno aunque tengo un error como el siguiente:
timeouts are not supported on this stream. silverlight
A que se deberá, que podré estar haciendo mal ?
Gracias.