Pregunta: | 55115 - DESCARGAR HTTP CON WINSOCK |
Autor: | Ignacio Martín Cordón |
Tengo una rutina que conecta a una dirección web mediante winsock y solicita un fichero usando el comando:
oSOCK.SendData("GET "+cOrigen+" HTTP/1.1"+CHR(13)+CHR(10)+"Host: "+cHost+CHR(13)+CHR(10)+"Accept: */*"+CHR(13)+CHR(10)+"Connection: close"+CHR(13)+CHR(10)+CHR(13)+CHR(10)) Mi problema es que cuando el documento que se trae es pequeño (pocos megas) funciona correctamente casi el 100% de las veces. Pero con documentos de mayor tamaño pasan cosas raras como por ejemplo: · Sólo un 3% de las veces llega a descargar el 100% del documento. Casi siempre se desconecta el socket cuando falta un paquete por llegar. · La información que se recibe no es correcta. He comparado los paquetes que recibo con los que debería recibir y uno de cada 50 contiene errores. ¿Qué puede estar ocurriendo? Suprimir la cláusula "Connection: close" no tiene ningún efecto adverso ni positivo. Tampoco se aprecian mejoras sin en lugar de usar el método DataArrival empleo un timer llamando a GetData yo mismo. Gracias. |
Respuesta: | Claudio Romero |
En esta pagina
http://www.fpress.com/revista/Num9709/Sep97.htm Hay una rutina en Foxpro para bajar un archivo a disco de texto o binario por ej: DO VFPHTTP WITH "http://www.linux.org","c:linux.htm" o DO VFPHTTP WITH "http://mirror.pacific.net.au/linux/slackware/slackware-12.2/slackware/l/aspell-0.60.5-i486-2.tgz","c:aspell.tgz" Utiliza la api de wininet.dll, que funciona bien para archivos de cualquier tamaño, aunque yo la utilice desde delphi, son las mismas funciones. **Esta es la rutina PROCEDURE VFPHTTP LPARAMETER cURL, cNameFich *** Definición de constantes básicas #DEFINE INTERNET_OPEN_TYPE_PRECONFIG 0 *** Declaración de funciones del API DECLARE LONG GetLastError ; IN WIN32API DECLARE INTEGER InternetCloseHandle ; IN "wininet.dll" ; LONG hInet DECLARE LONG InternetOpen ; IN "wininet.dll" ; STRING lpszAgent, ; LONG dwAccessType, ; STRING lpszProxyName, ; STRING lpszProxyBypass, ; LONG dwFlags DECLARE LONG InternetOpenUrl ; IN "wininet.dll" ; LONG hInet, ; STRING lpszUrl, ; STRING lpszHeaders, ; LONG dwHeadersLength, ; LONG dwFlags, ; LONG dwContext DECLARE LONG InternetReadFile ; IN "wininet.dll" ; LONG hFtpSession, ; STRING @lpBuffer, ; LONG dwNumberOfBytesToRead, ; LONG @lpNumberOfBytesRead *** Apertura nInternet = InternetOpen( ; "pruebavfp", ; INTERNET_OPEN_TYPE_PRECONFIG, ; "", "", 0 ) IF nInternet = 0 MESSAGEBOX( "Error: " ; + LTRIM( STR( GetLastError() ) ) ; + " en InternetOpen.", 16 ) RETURN ENDIF *** Abrir el URL nFichHTTP = InternetOpenUrl ( ; nInternet, ; cUrl, ; NULL, 0, 0, 0 ) IF nFichHTTP = 0 MESSAGEBOX( "Error: " ; + LTRIM( STR( GetLastError() ) ) ; + " en InternetOpenUrl.", 16 ) InternetCloseHandle( nInternet ) RETURN ENDIF *** Abir el fichero en el cliente nFich = FCREATE( cNameFich ) *** Contruir las variables necesarias nTama = 0 nLen = 1 *** Bucle de lectura DO WHILE nLen # 0 cBuffer = REPLICATE( CHR(0), 2048 ) *** Leer del fichero en el servidor InternetReadFile( ; nFichHTTP, ; @cBuffer, ; LEN( cBuffer ), ; @nLen ) *** Escribir el fichero en el cliente FWRITE( ; nFich, ; SUBSTR( cBuffer, 1, nLen ) ) *** Aumentar el tamaño total nTama = nTama + nLen WAIT WIND "Recibidos " ; + LTRIM( STR( nTama ) ) NOWAIT ENDDO WAIT CLEAR *** Cerrar el fichero local FCLOSE( nFich ) *** Cierre del uso del API InternetCloseHandle( nInternet ) |