Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Internet (https://www.clubdelphi.com/foros/forumdisplay.php?f=3)
-   -   Problema para descargar archivo de Internet (https://www.clubdelphi.com/foros/showthread.php?t=81177)

HombreGordo 18-10-2012 21:10:11

Problema para descargar archivo de Internet
 
Saludos, tenía mucho tiempo que no venía jejeje. Quisiera que por favor me ayudaran con un problema que tengo, especialmente descargando un archivo de Internet. Estoy usando la función GetInetFile que conseguí de la web About.com, que muchas veces he encontrado la solución a mis problemas allí, aunque tiene un pequeño defecto. Funciona bien excepto: cuando estoy descargando un archivo de Internet y no hay conexión (por ejemplo: si el host no se consigue, o si desconecto el cable ethernet para emular que no hay internet, etc.). A veces me consigo con un archivo de 0kb (que está bien, con eso no hay problema), y a veces me consigo con que se ha quedado llenando el disco duro con un archivo que pesa varios Mb o inclusive varios Gb si me distraigo y no mato el proceso a tiempo. Quisiera que, si no hay internet, no se quedara llenando el disco duro como "a veces" puede pasar.
Código Delphi [-]
function GetInetFile (const fileURL, FileName: String): boolean;
 const
   BufferSize = 1024;
 var
   hSession, hURL: HInternet;
   Buffer: array[1..BufferSize] of Byte;
   BufferLen: DWORD;
   f: File;
   sAppName: string;
   countSize: int64;
 begin
  result := false;
  sAppName := ExtractFileName(Application.ExeName) ;
  hSession := InternetOpen(PChar(sAppName), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0) ;
  try
   hURL := InternetOpenURL(hSession, PChar(fileURL), nil, 0, 0, 0) ;
   try
    AssignFile(f, FileName) ;
    Rewrite(f,1) ;
    countSize:=0;
    repeat
     InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen) ;
     BlockWrite(f, Buffer, BufferLen);
     countSize:=countSize + 1;
    until (BufferLen = 0);
    CloseFile(f) ;
    result := True;
   finally
    CloseFile(f) ;
    InternetCloseHandle(hURL)
   end
  finally
   InternetCloseHandle(hSession)
  end
 end;

Pensé que poniéndole un contador de alguna manera detendría el bucle de escritura. Pensé en ponerlo así:
Código Delphi [-]
...
countSize:=0;
    repeat
     InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen) ;
     BlockWrite(f, Buffer, BufferLen);
     countSize:=countSize + 1;
    until (BufferLen = 0) or (countSize <= 314573);
...

Ah sí, el uso que le doy a la función, es este:
Código Delphi [-]
internetFile := 'http://api.twitter.com/1/statuses/user_timeline.xml?include_entities=false&include_rts=true&screen_name=twitterapi&count=15';
  localFileName := 'user_timeline.xml';
GetInetFile( internetFile, localFilename);

Así que debería ser compatible descargando y guardando el XML resultante (con el que no tengo problemas procesando hasta los momentos). Gracias de antemano.

ZayDun 18-10-2012 23:46:55

Puedes verificar si hay conexión antes de realizar la descarga con este ejemplo de escafandra que vi por el foro.

Código Delphi [-]
function Ping(Addr: PCHAR; Rep: integer = 3): boolean;
var
  WSA: TWSAData;
  hIcmpFile: Cardinal;
  Reply: ICMP_ECHO_REPLY;
  He: Phostent;
  n: Integer;
begin
  Result:= false;
  if WSAStartup(MAKEWORD(1, 1), WSA) <> 0 then exit;
  He:= gethostbyname(Addr);
  if He = nil then exit;
  hIcmpFile:= IcmpCreateFile;
  n:= 0;
  repeat
    Result:= IcmpSendEcho(hIcmpFile, PULONG(He.h_addr_list^)^, 0, 0, 0, 
                          PCHAR(@Reply), sizeof(ICMP_ECHO_REPLY), 1000) <> 0;
    if Result then
       Result:= Reply.Status = 0;
    inc(n);
  until Result or (n=3);
  IcmpCloseHandle(hIcmpFile);
  WSACleanup;
end;


La llamada la puedes hacer de esta manera.

Código Delphi [-]
if Ping('www.google.com') then
GetInetFile( internetFile, localFilename)
else
...

HombreGordo 20-10-2012 01:58:34

Así fue como lo resolví
 
Ah bueno tu solución también es válida, mira lo que conseguí en internet para ayudarme también, un TIdHTTP de Indy:
Código Delphi [-]
internetFile := 'http://api.twitter.com/1/statuses/user_timeline.xml?include_entities=false&include_rts=true&screen_name=twitterapi&count=15';
  localFileName := 'user_timeline.xml';
  try
  //GetInetFile( internetFile, localFilename);
  //URLDownloadToFile( nil, PWideChar(internetFile), PWideChar(localFilename), 0, nil);
  Http := TIdHTTP.Create(nil);
  try
    MS := TMemoryStream.Create;
    try
      Http.OnWork:= HttpWork;

      Http.Get(internetFile, MS);
      MS.SaveToFile(localFileName);

    finally
      MS.Free;
    end;
  finally
    Http.Free;
  end;
Y Http.Work es:
Código Delphi [-]
private
    { Private declarations }
    procedure HttpWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);

...

procedure TFormMain.HttpWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
var
  Http: TIdHTTP;
  ContentLength: Int64;
  Percent: Integer;
begin
  Http := TIdHTTP(ASender);
  ContentLength := Http.Response.ContentLength;

  if (Pos('chunked', LowerCase(Http.Response.TransferEncoding)) = 0) and
     (ContentLength > 0) then
  begin
    Percent := 100*AWorkCount div ContentLength;

    //MemoOutput.Lines.Add(IntToStr(Percent));
  end;
end;
Vean que también usé URLDownloadToFile de URLMon, pero no lo probé mucho realmente. Tal vez sirve mejor que este parapeto que tengo allí jajaja Gracias a todos por ayudarme :-)


La franja horaria es GMT +2. Ahora son las 10:24:59.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi