El próximo día 6 estaré en Iniciador Galicia

Si estás por Galicia la semana que viene y te animas, estaré hablando sobre email marketing y mi experiencia emprendedora en A Coruña para el evento Iniciador.


La charla será: “E-mail Marketing: Por qué Outlook no es suficiente (y tuvimos que crear MAILCast)”.


En ella contaré como comencé en el mundo del email marketing y acabamos llegando al desarrollo de nuestro producto, MAILCast. También compartiré las dificultades de la práctica de la disciplina, como compaginar el e-mail marketing con el social media y los trucos para no caer en el tan temido spam. Siguiendo la línea habitual de Iniciador, la charla, tendrá un marcado espíritu emprendedor, pero en esta ocasión estará centrada en la temática del email marketing.


Además si eres de los primeros en llegar te llevarás un ejemplar de nuestro último libro “The Emailing Experience. 49 formas de dar en el blanco“.


Toda la info aquí: http://iniciador.com/galicia/2010/04/27/iniciador-galicia-con-j-m-alarcon-krasis/

Enviar un archivo al navegador desde ASP.NET

Otra pregunta muy común entre los programadores principantes es de qué manera pueden enviar al navegador de sus usuarios desde una página ASPX los contenidos de un archivo que está en el servidor.


La mayoría conoce el método Write de la clase HttpResponse que se llama desde una página simplemente escribiendo:

Response.Write(«Hola desde mi página ASPX»);

que lo que hace es introducir en el código de la página actual ese mensaje. Este método no se suele utilizar ya que introduce el texto fuera del flujo normal de renderizado de la página y por lo tanto suele quedar al principio de la página, descolgado. Se incorporó más por compatibilidad con ASP 3.0 clásico que por otra cosa.


Sin embargo esto devuelve texto únicamente al cliente. ¿Qué pasa si queremos enviar contenidos binarios, como los de un archivo PDF o un DOCX?


Tipos MIME


Veamos un concepto básico de Internet explicado de manera somera para los propósitos que nos ocupan ahora: el envío de archivos.


El  protocolo en el que se basa la Web es HTTP (HyperText transfer Protocol). HTTP está basado en texto, es decir, que sólo soporta el trasiego de información en formato textual, y por lo tanto en teoría no soportaría la transferencia de archivos binarios. Sin embargo todos los días nos descargamos sin problemas a través de la Web archivos ejecutables, PDFs, etc… que son todos archivos binarios ¿cómo es posible?


Las extensiones MIME nacieron con el objetivo de aumentar la capacidad de codificación del correo electrónico. Éste soportaba únicamente los caracteres ASCII americanos (de 7 bits), claramente insuficientes para soportar, no ya datos binarios, sino los caracteres de muchos idiomas occidentales y por supuesto asiáticos. MIME ofrece formas de codificar otros datos diferentes a ASCII de manera que sean simples caracteres ASCII, por lo que de este modo se puede enviar por email cualquier tipo de información que deseemos. Si bien su origen está en el e-mail, las extensioes MIME se utilizan en todo Internet desde hace muchos años. De estas extensiones derivan los llamados tipos MIME o tipos de contenido. Se trata de identificadores para determinar el tipo de un contenido transferido a través de un protocolo de Internet.


Gracias a MIME se pueden transferir datos binarios a través de HTTP y con los tipos MIME el navegador sabe cómo interpretar un contenido que recibe y que no es una página HTML. ¿Nunca te ha pasado que intentas leer un PDF en una web por ahí y te salen muchos caracteres extraños en el navegador en vez de ver el PDF? Pues eso es porque el servidor no envía al navegador la cabecera apropiada indicando el tipo MIME del archivo.


Ya he hablado en otras ocasiones de problemas al descargar archivos debido a una mala configuración de tipos MIME: ¿Por qué hay ciertos tipos de archivos que no somos capaces de descargar de nuestro servidor Web?


Por todo esto es esencial que, antes de enviar un archivo desde nuestro código de servidor, establezcamos una cabecera HTTP especial llamada content-type que sirve para indicar el tipo MIME del archivo que vamos a enviar a continuación. Si no lo hacemos corremos el riesgo de que pase lo que acabo de describir.


En .NET es tan sencillo como escribir esto en el manejador o página que creemos:

Response.ContentType = «image/jpg»;

siendo la cadena el tipo MIME que vamos a indicar, en este caso el correspondiente a una imagen en formato JPEG.


Cada tipo de archivo tiene su tipo MIME correspondiente. Por ejemplo el de los PDF es «application/pdf», el de las hojas Excel 2007 (extensión .xlsx) es «application/vnd.openxmlformats-officedocument.spreadsheetml.sheet» o el de las Excel anteriores (.xls) es «application/vnd.ms-excel».


La IANA, el organismo encargada entre muchas otras cosas de estandarizar estos tipos, tiene una lista de tipos MIME estándar, y se interesan específicamente los de Microsoft Office en esta página tienes una lista muy completa.


Enviar el archivo


Vale, ya sabemos que hay que establecer el tipo MIME enla cabecera para que todo funciones, pero ¿cómo enviamos ahora el contenido del archivo al navegador?


Podemos usar el método BinaryWrite de la misma clase HttpResponse de la uqe hemos hablado antes. Éste permite escribir datos binarios directamente en la respuesta de la petición actual. Así, por ejemplo, podríamos leer el archivo desde disco y usar BinaryWrite para enviar sus contenidos en la respuesta.


No obstante la clase HttpResponse dispone de un método especial más directo y apropiado que nos permite enviar archivos directamente al cliente desde la propia página, control, controlador o manejador (estos últimos son los más recomendables para enviar archivos). Se trata de WriteFile. Este método tiene cuatro sobrecargas, pero lo habitual es que usemos la primera de ellas, que simplemente toma como parámetro la ruta en el disco del servidor del archivo que queramos enviar al cliente. Por ejemplo:

Response.WriteFile(Server.MapPath(«docs/informe.pdf»));

Esto transforma la ruta virtual en una ruta física con el método MapPath del servidor (así tendremos algo en la forma C:MiCarpetaDocsinforme.pdf), y luego se envía al cliente con WriteFile.


Más sencillo imposible.


Archivos grandes


Esto está muy bien para enviar archivos de tamaño relativamente pequeño. Dependerá del hardware de tu servidor pero, aunque con esto podrás enviar archivos de varios megas sin problemas, si los archivos son realmente grandes (cientos de megas) y tu servidor está muy saturado, el método empezará a devolver errores porque nos quedaremos sin memoria para que sea operativo.


Esto es un problema reconocido por Microsoft y, de hecho, es también fácil de solucionar, aunque un poco más tedioso. La solución consiste, como ya apuntaba al principio, en enviar el archivo en trozos más pequeños que se van leyendo y descartando.


En este artículo de la Knowledge Base de Microsoft:



PRB: Response.WriteFile cannot download a large file


se explica cuál es este problema y se da código de ejemplo tanto en VB como en C# de cómo realizar este envío troceado del que estoy hablando.


Espero que te resulte útil.


Posts relacionados en este blog:



· Problemas subiendo archivos al servidor con ASP.NET

Cómo llamar a una página Web desde código

<DISCLAIMER>Han pasado unos cuantos días desde que he podido postear algo nuevo. Me ha pillado de lleno el famoso volcán islandés que ha paralizado el tráfico aéreo en Europa, por lo que he estado atrapado varios días en Bruselas sin posibilidad de salir de allí y, lo que es peor, ¡sin ordenador ni Internet! :-S </DISCLAIMER>


Esta es una pregunta muy habitual que he visto por ahí y que realmente es muy sencilla de poner en marcha:



«¿Cómo puedo llamar a una página Web (o recurso remoto HTTP) desde mi propio programa y mostrar el resultado en mi aplicación?»


La respuesta es muy sencilla, pero no todo el mundo sabe cómo hacerlo. Básicamente hay que utilizar la clase WebRequest. Este método, por ejemplo, sirve para solicitar un determinado recurso a partir de su URL, que se le pasa como parámetro, devolviendo una cadena con el contenido del recurso (o generando una excepción si el recurso no existe o da un error):

	static string LeerRecursoWeb(string laUrl)
{
// Cear la solicitud de la URL.
WebRequest request = WebRequest.Create(laUrl);
// Obtener la respuesta.
WebResponse response = request.GetResponse();
// Abrir el stream de la respuesta recibida.
StreamReader reader = new StreamReader(response.GetResponseStream());
// Leer el contenido.
string res = reader.ReadToEnd();

// Cerrar los streams abiertos.
reader.Close();
response.Close();

// Devolver resultado
return res;
}


Cómo vemos es bastante directo. Ahora, por ejemplo, podemos mostrar los enlaces más relevantes sobre ASP.NET en Delicious usando el siguiente código (en este caso para una aplicación de consola, pero valdría para cualquier otra):

		Console.WriteLine(LeerRecursoWeb(«http://feeds.delicious.com/v2/RSS/popular/ASP.NET»));

Muy sencillo.


Los detalles importantes


Hay algunos detalles que merece la pena comentar.


La clase WebRequest es abstracta. Esto quiere decir que no se usa directamente, sino que se utiliza para crear otras clases derivadas que implementan los métodos apropiados según el protocolo a utilizar. Por ello existen en la plataforma .NET otras clases más especializadas como HttpWebRequest, FtpWebRequest o FileWebRerquest, especializadas en llamar a recursos por HTTP, por FTP y por el sistema de archivos respectivamente.


El método Create de la clase abstracta, en función de la URL que le pasemos, crea la clase derivada adecuada para gestionar el protocolo que se deba utilizar y obntener así el resultado. Gracias a ello, la función que pongo más arriba funcionaría también con las siguiente URLs:

		Console.WriteLine(LeerRecursoWeb(«ftp://ftp.miservidor.com/carpeta/miarchivo.txt»));
Console.WriteLine(LeerRecursoWeb(«file://c:MiCarpetaMiarchivo.txt»));

De este modo el código se adapta a la URL usando la clase más apropiada en cada caso, lo que nos da mucha flexibilidad.


Por supuesto si quisiésemos restringir el uso a un protocolo concreto, como solamente el HTTP, es posible usar de manera directa cada una de estas clases especializadas y el código sería igual.


También existen otras clases especializadas, como por ejemplo WebClient, que nos permiten más control y enviar datos además de recibirlos, pero para responder a la pregunta planteada y poder empezar a investigar un poco por tu cuenta tienes material más que de sobra 🙂


NOTA: Por cierto, hay que incluir los espacios de nombres System.IO y System.Net, no te olvides…

Krasis cumple hoy 10 años, y el regalo te lo hacemos nosotros…

Porque queremos celebrarlo contigo. Así que lo que compres hoy en nuestra tienda on-line te saldrá a la mitad de precio.



Libros o cursos, da igual.


Para comprar a este precio sólo tienes que:



1.- Ir a la tienda
2.- Meter en el carrito lo que quieras comprar (una unidad de cada cosa máximo)
3.- Y a la hora de pagar usar el siguiente cupón de descuento:




ANIV2010


¡Listo!


Esperamos que te guste. No se cumplen 10 años todos los días y eso, en una empresa, ya empieza a ser un tiempo respetable 🙂


*(horario de España, hasta las 23:59 GMT+2 del 7 de Abril de 2010).

Un año más reconocido como Most Valuable Professional por Microsoft

Y van seis años seguidos. Este 2010 será el séptimo 🙂


Esta vez me han hecho sufrir un poco porque el correo electrónico que envían en el que te notifican amablemente que se te ha concedido el galardón, este año se quedó atrapado en nuestro filtro anti-spam corporativo, en el servidor. Quizá deberían empezar a pensar en incluir algunas medidas de entregabilidad en sus mensajes.


El caso es que este premio reconoce las contribuciones a la comunidad hechas en el último año (como este blog, mi libro sobre ASP.NET 4.0 de lectura gratuita en Internet, o unas cuantas conferencias que imparto cada año entre otras muchas cosas) así como el buen nivel técnico del premiado, así que estoy tan contento como siempre (o más).


Nos seguimos viendo por aquí, por twitter, Facebook, y muchos sitios más…