simplemente le cambiamos la extensión al archivo... y podemos convertirlo en archivo.gif o en archivo.pdf, etc.
La pregunta es:
Se puede validar el tipo de archivos que subimos al servidor?
me dirás: claro pes'... simplemente lo enlazo a un control asp:RequiredFieldValidator...
Nooooo, eso es simplemente para que el usuario obligatoriamente elija un archivo cualquiera, cero de nota!!!
Pero en parte sirve.
ah, entonces además lo enlazo a un control asp:RegularExpressionValidator... ahí le pongo una expresión regular para verificar que la extensión del archivo es la que mi aplicación permite... y zas!! todo controlado!!
hmmm, estás mejorando te diría... porque no es del todo cierto.
El control asp:RegularExpressionValidator sólo sirve para validar que la ruta ingresada en el control FileUpload cumpla con una expresión regular específica, por ejemplo un texto que termine en .gif
Pero, en parte sirve.
y a qué viene todo esto?
Imagínate tío que hagas una aplicación web que permita la subida de imágenes... pero alguien deshonesto renombra un virus.exe, y le llama imagen.jpg ...luego a través de un utilitario que te regala... renombra y activa el virus sobre tu PC... y ya sabes que tener un virus en la PC no es una experiencia agradable.
Esto, por poner un ejemplo no es cierto? porque pueden haber mil experiencias.
Entonces, si mis validaciones no sirven... qué puedo hacer? estoy perdido!!!
No estás perdido, vamos a analizar una simpática forma de verificar si el archivo que están intentando subir al servidor es válido.
El caso es el sgte:
Mi aplicación web debe sólo permitir la subida de archivos de tipo imagen... gif, bmp, png y jpg... nada más para empezar.
Para esto, a la página web le añadiremos un control asp:FileUpload, un asp:RequiredFieldValidator, un asp:RegularExpressionValidator, un asp:Label (para los mensajes desde el servidor) y un asp:Button
La expresión regular que valida el tipo de archivos que van al servidor la vamos a poner en el web.config
[appSettings]
[add key="ImageType" value="^.*(([^\.][\.][bB][mM][pP])([^\.][\.][gG][iI][fF])([^\.][\.][pP][nN][gG])([^\.][\.][jJ][pP][gG]))$"/]
[/appSettings]
Luego esa expresión regular le asigno al asp:RegularExpressionValidator en el Page_Load...
RegularExpressionValidator1.ValidationExpression = _
System.Configuration.ConfigurationManager.AppSettings("ImageType")
cómo? que por qué no se la asigno de frente en el html?
porque quiero centralizar la expresión regular... ya que se va a usar más de una vez...y si modifico la expresión regular, sólo tendría que modificarla en el web.config.
Hasta aquí, las validaciones se hacen en el cliente… pero para asegurarnos vamos del lado del servidor.
Las funciones que realmente van a hacer el trabajo sucio de validar si el archivo que estás intentando subir no ha sido renombrada en su extensión son las sgtes:
<System.Runtime.InteropServices.DllImport("urlmon.dll", CharSet:=System.Runtime.InteropServices.CharSet.Unicode, ExactSpelling:=True, SetLastError:=False)> _ Shared Function FindMimeFromData(ByVal pBC As IntPtr, <System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)> ByVal pwzUrl As String, <System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPArray, ArraySubType:=System.Runtime.InteropServices.UnmanagedType.I1, SizeParamIndex:=3)> ByVal pBuffer As Byte(), ByVal cbSize As Integer, <System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)> ByVal pwzMimeProposed As String, ByVal dwMimeFlags As Integer, _ ByRef ppwzMimeOut As IntPtr, ByVal dwReserved As Integer) As Integer End Function Public Shared Function getMimeFromFile(ByVal file As HttpPostedFile) As String Dim mimeout As IntPtr Dim MaxContent As Integer = DirectCast(file.ContentLength, Integer) If MaxContent > 4096 Then MaxContent = 4096 End If Dim buf As Byte() = New Byte(MaxContent) {} file.InputStream.Read(buf, 0, MaxContent) Dim result As Integer = FindMimeFromData(IntPtr.Zero, file.FileName, buf, MaxContent, Nothing, 0, _ mimeout, 0) If result <> 0 Then System.Runtime.InteropServices.Marshal.FreeCoTaskMem(mimeout) Return "" End If Dim mime As String = System.Runtime.InteropServices.Marshal.PtrToStringUni(mimeout) System.Runtime.InteropServices.Marshal.FreeCoTaskMem(mimeout) Return mime.ToLower() End Function
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click Dim RealMimeType As String = getMimeFromFile(FileUpload1.PostedFile) End SubNota: este post ha sido modificado de su versión original, gracias a un usuario que detectó que algunas verificaciones que hacía ya no funcionaban en estos momentos.
Y eso es todo. ;)
2 comentarios:
Hola, acabo de probar esta función que cuentas, pero resulta que si le cambio la extensión de un exe a pdf, y lo subo, el content type me tira application/pdf y pasa como si nada. No sabes de que otra forma puedo detectar que es un exe disfrazado???
Muchas gracias
Hola Raul Abel,
Por favor lee el post, lo he actualizado según lo que comentas.
Saludos.
Publicar un comentario