FileUpLoad e ImagenThumbnail

Una de las limitaciones del control fileupload de asp.net 2.0 es que luego de seleccionar el archivo, en este caso una imagen, se requiere un botón adicional para subir la imagen al servidor y previsualizarla. Este post pretende mostrar una manera (lo que no significa que sea la única ni la mejor) de realizar ambos pasos, subir la imagen al servidor y realizar el thumbnail con solo seleccionar la imagen.

Se va utilizar Visual Studio 2005 y por ende asp.net 2.0 (probado para IE 6.0 en adelante y Mozilla-Firefox 2.0.6).

Los controles en la pagina van a ser:

-FileUpload (el de la version 2.0) (UBICACIONTMP – nombre del control)

-Un hidden control (UBICACION – nombre del control)

-Un control Image (IMAGEN – nombre del control)

-Un LinkButton visible pero sin la propiedad text, lo que lo convierte en invisible pero que viaja al explorador. Caso contrario no viaja (LinkPostBack – nombre del control) Se usan los siguientes namespace:

Se usan los siguientes namespace:

Imports System.IO
Imports System.Net
Imports System.Drawing.Imaging

En el código de vb.net

Una varible global dentro de la pagina:

Dim imgThum As String

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Response.BufferOutput = False ‘No se va a almacenar en el buffer
Response.Clear() ‘Borra toda la salida de contenido de la secuencia del búfer
Response.ClearHeaders() ‘Borra todos los encabezados de la secuencia del búfer
‘JS que entra en accion cuando se haga click en browse del control fileupload
UBICACIONTMP.Attributes.Add(“onclick”, “javascript:asignarRutaFoto();”)
‘JS para validar que apriete el boton browse con el mouse y no teclee la ruta a mano
UBICACIONTMP.Attributes.Add(“onkeypress”, “javascript:return validarkey();”)
End Sub

Private Sub MostrarImagen()
Dim strFileName As String = UBICACION.Value
Dim Filename As String = system.IO.Path.GetFileName(strFileName)
Dim objImage, objThumbnail As System.Drawing.Image
Dim strServerPath As String
Dim shtWidth As Integer
Dim shtHeight As Integer
strServerPath = Server.MapPath(“ImagenesCarpeta\”)
strFileName = strServerPath & Filename
Dim my_stream As IO.Stream = Nothing
Try
‘Creo un stream para poner la imagen y despues hacer un OBJ con el metodo fromStream que cierra el archivo. Esto es importante para que la imagen no quede abierto en el servidor.
my_stream = File.OpenRead(strFileName)
objImage = Drawing.Image.FromStream(my_stream)
shtWidth = 100
shtHeight = objImage.Height / (objImage.Width / shtWidth)
Response.Clear()
objThumbnail = objImage.GetThumbnailImage(shtWidth, _
shtHeight, Nothing, System.IntPtr.Zero)

imgThum = “~/ImagenesCarpeta/” + “TUM_” + + “TUM_” + Filename ‘Para saber que se trata de un thumbnail
objThumbnail.Save(Server.MapPath(“ImagenesCarpeta\”) + “TUM_” + Filename, ImageFormat.Jpeg)
IMAGEN.Visible = True
IMAGEN.ImageUrl = “~/ImagenesCarpeta/” + “TUM_” + Filename

Catch ex As Exception
Throw ex
Finally
objImage.Dispose()
objImage = Nothing
objThumbnail.Dispose()
objThumbnail = Nothing
my_stream.Dispose()
my_stream = Nothing
End Try
End
Sub

Private Function CargarFotografia() As String

Dim strFileName As String = UBICACIONTMP.PostedFile.FileName
Dim Filename As String = Path.GetFileName(strFileName)
Dim extension As String = Path.GetExtension(strFileName).ToLower

Try

If extension <> “.png” AndAlso extension <> “.jpg” AndAlso extension <> “.bmp” Then
Throw New Exception(“El archivo ingresado no es una imagen”)
End If
UBICACIONTMP.PostedFile.SaveAs(Server.MapPath(“\ImagenesCarpeta\”) + Filename)
UBICACION.Value = NombreImagenServidor(extension) ‘asigno el nuevo nombre de la img al hide
File.Move(Server.MapPath(“\ImagenesCarpeta\”) + Filename, _ Server.MapPath(“\ImagenesCarpeta\”+ UBICACION.Value))

Return UBICACION.Value

Catch ex As IOException
Throw
Catch ex As UnauthorizedAccessException
Throw
Catch ex As Exception
Throw
End Try

End Function

Public Function NombreImagenServidor(ByVal extension As String) As String
Dim nombre As String
Dim nRandom As New Random
nr As String = Convert.ToString(nRandom.Next(0, 32000))
nombre = “TMP_” + Format(Date.Today, “dd.MM.yyyy”) + “_” + nr + extension
nRandom = Nothing

Return nombre
End Function

Protected Sub linkPostBack_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles linkPostBack.Click
Try
If UBICACIONTMP.HasFile = True Then ‘ si tiene un archivo
CargarFotografia()
MostrarImagen()

End If
Catch ex As Exception
lblMensajes.Text = “Ha ocurrido la Siguiente Excepcion: “ & ex.Message
End Try
End Sub

Y del lado del cliente se utiliza este script que me permite correr un ciclo hasta que el usuario le de click (luego de elegir la imagen) al botón aceptar, ahí es donde realizo un postback

<script language=”JavaScript” type=”text/javascript”>
var x=5000;
var Guardar;
function asignarRutaFoto()
{
var tiempo,tiempo2;
if(x>=0)
{
x-=1;
if (document.form1.UBICACIONTMP.value==“”)
{ tiempo2=setTimeout(“asignarRutaFoto()”,50); }
else
{document.form1.UBICACION.value=document.form1.UBICACIONTMP.value; x=-1;
__doPostBack(‘linkPostBack’,); }
}

}
function validarkey()
{
// Para que use el browse y no teclee la ruta
alert (“Presione el boton Browse para buscar una foto”)
return false;
}</script>

Esta es la pagina incial:
Foto 1

Esta es la pagina luego de seleccionar la imagen:

foto 2

Asi queda el directorio donde se almacenan las imagenes, la que comienza con TUM es para visualizar el Thumbnail y la otra es la imagen real.

foto 3

Saludos, espero les sea util a quien lo lea.

Descargar el proyecto aquí

11 comentarios para “FileUpLoad e ImagenThumbnail”

  1. Alejandro Hernández Dice:

    Excelente artículo Fernando, felicitaciones por tu nuevo Blog.

  2. JRM Dice:

    Muy bueno al artículo, me sirvió mucho
    Gracias y felicitaciones

  3. Leo Robles Dice:

    Q tal me ha servido de mucho tu articulo, pero quisiera saber como le puedo hacer para mostrar la imagen agregando un boton, y al momento de darle click al boton mostrar la imagen seleccionada en un control image para luego guardar todo el registro en la base de datos, gracias…

  4. Fernando Sanchez Dice:

    bueno leo, mira en este momento no tengo un VS 2005 para poder probar lo que te digo con el codigo, pero lo que podes hacer es cuando se ejecuta el evento click de LinkPostBack, osea cuando seleccionas una imagen fijate q yo ahi llamo a CargarFotografia() y MostrarImagen() vos ahi podes hacer lo mismo pero dejarlo oculto por ejemplo poniendo algo asi Nombre_del_Control_a_Ocultar.Style(“display”) = “none” (para que esto funcione el control o el TD o TR tiene que ser runat=server) , despues de esta linea IMAGEN.ImageUrl = “~/ImagenesCarpeta/” + “TUM_” + Filename y seguido de eso le mostras un boton y cuando el tipo le da click al boton podes hacer una funcion JS que directamente muestre lo que vos ya tenes en pantalla pero oculto algo asi como:
    var ctl=”Nombre_del_Control_a_Mostrar”;
    document.getElementById(ctl).style['display']=”;
    eso en el onclick de ese boton(en un script en la pagina), no lo testie pero tendria que funcionar, y para despues mandar la imagen a la Base tendrias que modificar lo que hago yo (osea guardarla en jpg en el servidor) aca encontre algo en la web, esta en C#, http://www.netveloper.com/contenido2.aspx?IDC=359_0 ,lo que podes hacer es guardar el objeto Byte (byteImage) en session y cuando decidis mandarlo a la base lo mandas con todo junto porque en el link que te pase lo mande de una a la Base.
    Cuando tenga a mano un VS2005 lo voy a modificar para adaptar esto de mandarlo a la BD en lugar de guardarlo en una carpeta.
    Espero te sirva!

  5. Roxana Dice:

    Hola Fernando !!
    Excelente articulo… Además de que te explicas muy bien, todo lo entendi a la perfeccion. a la primera me salio.
    Me sirvio de mucho, yo queria guardara inmediatamente al momento de buscar la imagen en el fileupload sin tener q agregar un boton de cargar… q era lo que yo hacia.
    Ya ahora solo voy a ajustarlo para q me deje no solo guardar imagenes sino q tambien archivos.
    Gracias!!
    Y espero sigas con estos articulos.

  6. KradleWish Dice:

    primero lo hice funcionar tu proy, pero una ves que lo lleve a mi proy todas las funciones y los javascript’s y todos los controles con cuales tiene que funcionar me da el siguiente error:

    1.- que cuando ingresa al formulario donde esta implementado lo tu histes es como se metiera en un bucle haciendo postback n-veces por unos segundos (mas o menos unos 25 seg).

  7. Fernando Sanchez Dice:

    Bueno antes que nada gracias al comentario anterior de roxana y en cuanto a kradlewish, la verdad que no tengo idea porque pasa. A simple vista se me ocurre que puede estar entrando indefinidas veces por esta linea:
    __doPostBack(‘linkPostBack’,”) eso hace postbacks desde javascript.
    Fijate si podes poner algo de codigo para poder darte una mano.
    Saludos!

  8. Elyt Dice:

    Hola.
    Soy principiante en aspnet y queria preguntarte la capeta ImagenesCarpeta\ es simplemente una carpeta creada en el sitio web desde la raiz?????? mi problema es que pareciera que se carga pero no muestra nada en la imagen

  9. Elyt Dice:

    Amigo gracias por el articulo… segui probandolo y ya me funciono, ahora voy a tratar de adaptarlo a c# y aumentar funcionalidad de acuerdo a lo que necesito…pero este articulo fue realmente valioso para mi…mil gracias….Espero encontrar mas articulos tuyos ..son muy buenos

  10. Fernando Sanchez Dice:

    Me alegro que te haya servido.

    gracias y un Saludo!

  11. Elyt Dice:

    Hola amigo espero que estes muy bien

    Disculpa la molestia pero no se si te sea posible poner el codigo en c# o solo CargarFotografia(), yo lo cambie a c# pero no me funciona…parece que se cargara las imagenes a la carpeta pero en realidad no se carga nada.

    De antemano gracias por tu ayuda

Escribe un comentario