How to retrieve a file from Internet via HTTP?

后端 未结 6 2115
天命终不由人
天命终不由人 2020-12-30 17:46

I want to download a file from Internet and InternetReadFile seem a good and easy solution at the first glance. Actually, too good to be true. Indeed, digging a bit I have s

相关标签:
6条回答
  • 2020-12-30 18:11

    I basically do the same as you do. For me it works fairly flawlessly.

    The only differences between my code and your code is I have an INTERNET_FLAG_RELOAD parameter to force a download from the file and not the cache. You can try that and see if it works better:

      hURL := InternetOpenURL(hSession, PChar(fileURL), nil, 0, INTERNET_FLAG_RELOAD, 0) ; 
    

    Also check for an internet connection before downloading. Do this:

      dwConnectionTypes := INTERNET_CONNECTION_MODEM
                     + INTERNET_CONNECTION_LAN
                     + INTERNET_CONNECTION_PROXY;
      InternetConnected := InternetGetConnectedState(@dwConnectionTypes, 0);
      if InternetConnected then ...
    
    0 讨论(0)
  • 2020-12-30 18:11

    I recommend Synapse. It's small, stable and easy-to-use (no need of any external libraries).

    Example from httpsend.pas

    function HttpGetText(const URL: string; const Response: TStrings): Boolean;
    var
      HTTP: THTTPSend;
    begin
      HTTP := THTTPSend.Create;
      try
        Result := HTTP.HTTPMethod('GET', URL);
        if Result then
          Response.LoadFromStream(HTTP.Document);
      finally
        HTTP.Free;
      end;
    end;
    
    0 讨论(0)
  • 2020-12-30 18:14

    Instead of fiddling with the WinAPI, the ExtActns unit provides just what you need for downloading to a file.

    procedure TMainForm.DownloadFile(URL: string; Dest: string); 
    var 
      dl: TDownloadURL; 
    begin 
      dl := TDownloadURL.Create(self); 
      try 
        dl.URL := URL; 
        dl.FileName := Dest; 
        dl.ExecuteTarget(nil); //this downloads the file 
        dl.Free; 
      except 
        dl.Free; 
      end; 
    end; 
    

    Under the hood, it uses URLDownloadToFile from the URLMon library - which is part of IE, and therefore part of Windows.

    TDownloadURL doesn't handle any timeout for you - it doesn't look like such a thing is supported in URLMon at all, although there could be some default timeout that causes the call to fail - but you could use the OnProgress event on TDownloadURL to get notified when something happens, and then do something in another thread if it's been too long since the last callback.

    0 讨论(0)
  • 2020-12-30 18:18

    My personal favorite is using the WebHttpRequest component from importing the "Microsoft WinHTTP Services" type library: http://yoy.be/item.asp?i142

    var
      w:IWebHttpRequest;
      f:TFileStream;  
      os:TOleStream;
    begin 
      w:=CoWebHttpRequest.Create;
      w.Open('GET',SourceURL,false);
      w.Send(EmptyParam);
      os:=TOleStream.Create(IUnknown(w.ResponseStream) as IStream);
      f:=TFileStream.Create(DestinationFilePath,fmCreate);
      os.Position:=0;
      f.CopyFrom(os,os.Size);
      f.Free;
      os.Free;
      w:=nil;
    end;
    
    0 讨论(0)
  • 2020-12-30 18:25

    Here's some sample code that uses Indy. This code is for Delphi 2010 (with Indy 10?), but the code for Delphi 7 would be similar. I've used Indy for years with D7 and have been very happy with it. I think in D7 we use Indy 9. Check if you need to download a new version...

    You can use OnWork and OnWorkBegin to add a progress meter if you need to.

    This code I excerpted from a bigger piece, editing it a bit. I did not try compiling it, but it will give you a good starting place.

    function Download( const aSourceURL: String;
                       const aDestFileName: String;
                       out   aDownloadResult: TDownloadResult;
                       out   aErrm: String): boolean;
    var
      Stream: TMemoryStream;
      IDAntiFreeze: TIDAntiFreeze;
    begin
      aDownloadResult := DROther;
      Result := FALSE;
      fIDHTTP := TIDHTTP.Create;
      fIDHTTP.HandleRedirects := TRUE;
      fIDHTTP.AllowCookies := FALSE;
      fIDHTTP.Request.UserAgent := 'Mozilla/4.0';
      fIDHTTP.Request.Connection := 'Keep-Alive';
      fIDHTTP.Request.ProxyConnection := 'Keep-Alive';
      fIDHTTP.Request.CacheControl := 'no-cache';
      IDAntiFreeze := TIDAntiFreeze.Create;
    
      Stream := TMemoryStream.Create;
      try
        try
          fIDHTTP.Get(aSourceURL, Stream);
          if FileExists(aDestFileName) then
            DeleteFile(PWideChar(aDestFileName));
          Stream.SaveToFile(aDestFileName);
          Result := TRUE;
          aDownloadResult :=drSuccess;
        except
          On E: Exception do
            begin
              Result := FALSE;
              aErrm := E.Message + ' (' + IntToStr(fIDHTTP.ResponseCode) + ')';
            end;
        end;
      finally
        Stream.Free;
        IDAntiFreeze.Free;
        fIDHTTP.Free;
      end;
    end;  { Download }
    
    0 讨论(0)
  • 2020-12-30 18:26

    Solved using improved version of the above code. (it still does not solve all issues - MS does not actually implemented full support for server time out)

    The connection does not timeout while downloading file from internet

    0 讨论(0)
提交回复
热议问题