viernes, 10 de febrero de 2017

Descargar PDF con Asp Clásico

Hace unos días estuve buscando en Internet alguna función en ASP clásico que me permitiera descargar archivos PDFs.

Y encontré éstas funciones que permiten descargar un fichero dada la ruta donde se encuentra y el nombre del archivo:

'*******************************FUNCIÓN 1*****************
Function downloadFile(strPathAndFile, strFileName)
    Dim objFso
    Dim objStream
    If strPathAndFile <> "" Then
        Set objFso = Server.CreateObject("Scripting.FileSystemObject")
       'If objFso.FileExists(strPathAndFile) Then
            Response.AddHeader "Content-disposition", "filename=" & strFileName
            Response.ContentType = "application/octet-stream"
            Response.AddHeader "Pragma", "no-cache"
            Response.AddHeader "Expires", "0"
            Set objStream = Server.CreateObject("ADODB.Stream")
            objStream.Type = 1
            objStream.Open
            objStream.LoadFromFile strPathAndFile
            Response.BinaryWrite(objStream.Read())
            objStream.Close
            Set objStream = Nothing
        Else
            Response.Write "La ruta del fichero no existe."
        End If
        Set objFso = Nothing
    End If

End Function

'*******************************FUNCIÓN 2***************** 
Function downloadFile(strPathAndFile, strFileName)
    Response.Buffer = False
    Dim objStream
    Set objStream = Server.CreateObject("ADODB.Stream")
    objStream.Type = 1 'adTypeBinary
    objStream.Open
    objStream.LoadFromFile(strPathAndFile)
    Response.ContentType = "application/x-pdf"
    Response.Addheader "Content-Disposition", "attachment; filename=" & strFileName
    Response.BinaryWrite objStream.Read
    objStream.Close
    Set objStream = Nothing

End Function

Sin embargo, en ambos casos salió el siguiente error "Es posible que la página web http:// ...  esté temporalmente inactiva  o que se haya trasladado definitivamente a otra dirección



Para solucionar este problema tienes que:

1. Incluir el .Mode encima del .Open y con el valor 3 para prevenir errores de bloqueo de acceso si están accediendo al archivo varias personas al mismo tiempo.

objStream.Mode = 3

objStream.Open
objStream.Type = 1


2. Cambiar: Response.ContentType "application/octet-stream"
por: Response.ContentType = "xxx/xxx"

3. Antes de Response.AddHeader Incluir Response.Clear

4. Después de cerrar el FileSystemObject incluir: response.end


Quedando el código como sigue:

Function downloadFile(strFilePath, strFileName)
   
    Set objFSO = Server.CreateObject("Scripting.FileSystemObject")
   
    If objFSO.FileExists(strFilePath) Then
        Set objFile = objFSO.GetFile(strFilePath)
        intFileSize = objFile.Size
        Set objFile = Nothing

        Response.Clear
        Response.AddHeader "Content-Disposition","attachment; filename=" & strFileName
        Response.ContentType = "xxx/xxx"
        Response.AddHeader "Content-Length", intFileSize

        Set objStream = Server.CreateObject("ADODB.Stream")
        objStream.Mode = 3
        objStream.Open
        objStream.Type = 1
       
        objStream.LoadFromFile strFilePath

        Do While Not objStream.EOS And Response.IsClientConnected
            Response.BinaryWrite objStream.Read(1024)
            Response.Flush()
        Loop

        objStream.Close
        Set objStream = Nothing

    End if
   
    Set objFSO = Nothing
    response.end

End Function

 

martes, 15 de noviembre de 2016

ASP Clásico: QR en PNG convertirlo en JPG

Obtener la imagen del QR de una url y convertirla de PNG a JPG

En asp clásico para obtener la imagen del QR de una url he hecho lo siguiente:

dim enlace : enlace = "http://vegamatrica.blogspot.com.es/"
'URL de creación del QR
dim url : url = "https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl="&enlace&"&choe=UTF-8"


Indicar que a pesar de que la API de Google Charts está obsoleta, pensaba utilizarla. 
Ver: https://developers.google.com/chart/image/docs/making_charts

'DONDE:
'chs->tamaño del código QR (longitud x altura)
'cht->con su valor de argumento "qr" indica que el API Google Charts debe generar un código QR.
'chl->contiene la URL a la que se generará el QR.
'choe->(opcional) indica la codificación del código QR, por defecto UTF-8.


'ruta donde guardo la imagen del QR.
dim rutaGuardarQR : rutaGuardarQR = "C:\proyectos"

'Nombre de la imagen del QR que se guarda como PNG
dim nombreImagenQR : nombreImagenQR = "imagenQR.png"

call saveImageFromUrl(url, rutaGuardarQR, nombreImagenQR)

'La función saveImageFromUrl permite guardar la imagen del QR en la carpeta correspondiente. Convirtiendo la imagen de PNG a JPG


function saveImageFromUrl(strFileURL, imageLocation, image)

    server.scripttimeout = 60 * 20


    ' Fetch the file
    Dim objXMLHTTP : Set objXMLHTTP = CreateObject("MSXML2.XMLHTTP")
    objXMLHTTP.open "GET", strFileURL, false
    objXMLHTTP.send()

    If objXMLHTTP.Status = 200 Then
        Dim objADOStream :  Set objADOStream = CreateObject("ADODB.Stream")
        objADOStream.Open
        objADOStream.Type = 1 'adTypeBinary
        objADOStream.Write objXMLHTTP.ResponseBody
        objADOStream.Position = 0 'Set the stream position to the start
   
   
        Dim objFSO : Set objFSO = Createobject("Scripting.FileSystemObject")
        If objFSO.Fileexists(imageLocation) Then objFSO.DeleteFile imageLocation
   
            Set objFSO = Nothing
            objADOStream.SaveToFile imageLocation & "/" & image
            objADOStream.Close
            Set objADOStream = Nothing


            'Convertir la imagen del QR PNG en JPG
            dim imageMagick: Set imageMagick = CreateObject("ImageMagickObject.MagickImage.1")
            dim imageConverted
            imageConverted = imageMagick.Convert(imageLocation & "/" image, imageLocation & "/" & "imagenQR.jpg")

        End if
    Set objXMLHTTP = Nothing
end function   


Al ejecutar la función "saveImageFromUrl" lanzó el siguiente error:

"El componente ActiveX no puede crear el objeto: 'ImageMagickObject.MagickImage.1'" a pesar de haberlo registrado con el siguiente comando:

 regsvr32 "C:\Archivos de programa\ImageMagick-6.2.3-Q8\ImageMagickObject.dll"

*Lo que se puede ver en la siguiente imagen de regsvr32.exe



Como necesito convertir la imagen del QR de PNG en JPG, y después de dedicarle un día en intentar solucionar ese problema y sin obtener soluciones, he decidido hacer la función en php y llamar a ese php desde el asp.

Para hacer la función en php utilicé el código de "PHP QR Code" http://phpqrcode.sourceforge.net por su facilidad de uso.

  1. Me descargué la biblioteca "phpqrcode"
  2.  En mi PHP:
include('../phpqrcode/qrlib.php');

$url = "http://vegamatrica.blogspot.com.es/"
$filePath = "C:\proyectos"

QRcode::png($url, $filePath); //$filePath ruta donde guardaré la imagen del QR en formato


if (!file_exists($filePath."\imagenQR.png")) {      
    QRcode::png($urlCompletaTurispain, $pngAbsoluteFilePath);
    $image = imagecreatefrompng($filePath."\imagenQR.png");
    imagejpeg($image, $filePath."\imagenQR.jpg", 70); 


     //convertimos la imagen png a jpg con calidad 70%   
    imagedestroy($image);

 
    //Borramos la imagen png       
    unlink($pngAbsoluteFilePath);
        

}else{
    echo "La ruta no existe";
}   

Y finalmente pude utilizarla en el ASP.




jueves, 10 de noviembre de 2016

ASP Clásico: Descarga y eliminación de fichero y Redirección de url



En ASP Clásico para descargar un fichero, por ejemplo PDF, y luego eliminarlo, encontré este código en Internet:

  • downloadFile es una función que permite descargar el fichero, pasándole como parámetros la ruta del fichero  y el nombre del fichero. Ejemplo: strPathAndFile= "C:\ficheros /nombreFichero.pdf" y strFileName= "nombreFichero.pdf"  

function downloadFile(strPathAndFile, strFileName)
  Dim objFso
  Dim objStream
  If strPathAndFile <> "" Then
    Set objFso = Server.CreateObject("Scripting.FileSystemObject")
    If objFso.FileExists(strPathAndFile) Then
     Response.AddHeader "Content-disposition", "filename=" & strFileName
      Response.ContentType = "application/octet-stream"
      Response.AddHeader "Pragma", "no-cache"
      Response.AddHeader "Expires", "0"
      Set objStream = Server.CreateObject("ADODB.Stream")
      objStream.Type = 1
      objStream.Open
      objStream.LoadFromFile strPathAndFile
      Response.BinaryWrite(objStream.Read())
      objStream.Close
      Set objStream = Nothing
    Else
      Response.Write "La ruta del fichero no existe."
    End If
    Set objFso = Nothing
  End If
End Function

  • Y para eliminar el fichero, esta función deleteFileFromServer donde fileRoute= "C:\ficheros /nombreFichero.pdf" (por ejemplo).

function deleteFileFromServer (fileRoute)
    Dim objFSO : Set objFSO = Createobject("Scripting.FileSystemObject")
    If objFSO.Fileexists(fileRoute) Then
       objFSO.DeleteFile fileRoute
       Set objFSO = Nothing
    else      
        response.write "No existe el fichero en la ruta especificada."
    end if
end function    

Ahora bien, en mi fichero asp llamé a las funciones de 

call downloadFile(rutaArchivo, nombreArchivo)
call deleteFileFromServer(rutaArchivo)

Y luego ponía una tercera línea response.end()y funcionaba perfectamente, sin embargo, al quitar el response.end()y redireccionar a la página:
response.redirect("miPagina.asp?accion=ok”) la descarga y eliminación dejaban de funcionar.

Si te ha pasado esto alguna vez, te cuento cómo lo solucioné:

Me cree un nuevo fichero .asp que contenía la descarga y eliminación del fichero y desde Jquery llamé a ese fichero utilizando
                                              
window.open(‘descargaEliminaFichero.asp’);

Y a continuación puse la redirección a mi página:

window.location.href = ‘miPagina.asp?accion=ok’;
               
Y listo, ya tenemos la descarga del fichero (en mi caso PDF), eliminación y  redirección.                              

jueves, 7 de julio de 2016

Peticiones a Clientes Web en ASP Clásico



En esta entrada aprenderás a extraer datos de Sitios Webs haciendo peticiones al servidor utilizando el lenguaje de programación ASP clásico.

1) Inicializar las variables

Response.Buffer = True
Dim xml

2) Decidir cómo crear el objeto

Con:

Set xml = Server.CreateObject("Microsoft.XMLHTTP")

O con:

Set xml = Server.CreateObject("MSXML2.ServerXMLHTTP")

En mi caso utilizaré “MSXML2.ServerXMLHTTP” porque cuando utilicé “Microsoft.XMLHTTP” en una Web dónde había una redirección, me mostraba error y no podía obtener la nueva Web a la que estaba redireccionando.

A continuación veamos algunas diferencias entre XMLHTTP y ServerXMLHTTP

XMLHTTP se utiliza, generalmente, en la comunicación cliente-servidor (por ejemplo, en una petición a un Servicio Web), también en transferencias de datos, por ejemplo utilizando el protocolo FTP. También permite el almacenamiento automático de la url en la memoria caché. XMLHTTP utiliza WinInet (Windows Internet Explorer) para su funcionamiento.

Por su parte ServerXMLHTTP está destinado a la comunicación entre servidores, aplicaciones clientes y procesamiento de peticiones entre clientes. En ServerXMLHTTP el estado se mantiene “activo”, es decir, la información enviada/recibida desde/hacia un destino se retiene en la conexión actual para ser utilizada en futuras transacciones de datos
ServerXMLHTTP crea una pila de cliente http, es decir, una sesión independiente del cliente http, lo que implica que pueden existir varias instancias activas del objeto ServerXMLHTTP en función de la memoria y la disponibilidad de conexiones. El objeto ServerXMLHTTP puede ser utilizado además para hacer peticiones/envío de datos de una aplicación a otra, incluso cuando se requiere que sea en tiempo real.

3) Abrir la conexión, en mi caso utilizaré el método POST aunque puedes utilizar GET u otro en dependencia del caso.

·         - site es el sitio Web al cuál quieres hacerle la petición.
·         - False es un indicador booleano que muestra si la llamada es o no asíncrona.

xml.Open "POST", site, False

4) Hacemos la petición con:

xml.Send

3) Si al hacer la petición te da un error puedes controlarlo con el típico try-catch aunque en ASP clásico se hace de esta manera:

Colocas este código al inicio de tu .asp “On Error Resume Next

Y luego después del xml.Send capturas el error (como aparece a continuación), en mi caso obligo a que el estado sea “Error 404” aunque lo puedes programar de forma diferente.

dim webStatus: webStatus = vbNullString
If Err.Number <> 0 Then
webStatus = ERROR_404
response.write "Error:" & Err.Number & " " & "Desc:" & Err.Description
else
webStatus = xml.status
end if
On Error GoTo 0

5)  Si el estado es “200”

if (webStatus = 200) then
      'Aquí puedes coger todos los datos que necesites
End if

Datos que puedes extraer de la Web

xml.responseText 'Código Html del sitio Web, mostrándolo por pantalla de esta manera response.write "<xmp>" & xml.responseText & "</xmp>"

xml.getOption(-1) 'Extrae la url de la Web, lo que nos ayudaría en caso de una redirección a comprobar si el “site” ha cambiado

Si quieres tener información de las páginas que enlaza nuestro sitio web en cuestión, aquí te dejo el código

'Declaración de Variables

Dim responseT : responseT = vbNullString
Dim registroExpresion : registroExpresion = vbNullString
Dim matches : matches = vbNullString
Dim http : http = vbNullString
Dim match : match = vbNullString

Set http = Server.CreateObject("WinHttp.WinHttpRequest.5.1")    
'http.SetTimeouts resolveTimeout, connectTimeout, sendTimeout, receiveTimeout
http.SetTimeouts 60000, 60000, 600000, 60000
http.Open "GET", site, False
http.Send

'Esperamos unos segundos a que termine la operación de envío asincrónico.
If http.WaitForResponse(5) Then
responseT = http.ResponseText
End If

Set http = Nothing
Set registroExpresion = New RegExp
registroExpresion.IgnoreCase = True
registroExpresion.Global = True

'Creamos la expression regular para extraer la url
registroExpresion.Pattern = "<a href=""(http|https)://(?!" & site & ")(.*?)"""

Set matches = registroExpresion.Execute(responseT)
If matches.Count > 0 Then
For Each match In matches
response.write "URL= " & match.SubMatches(1) & "<br/>"
Next
Else
response.write “No matches”
End If

*Aquí algunos enlaces que pueden ser de utilidad para el desarrollo de este tema:

Para probar expresiones regulares: http://regexr.com/

Sobre expresiones regulares:

Códigos de estados http