zoukankan      html  css  js  c++  java
  • Delphi 我的代码之简单封装WinHttpRequest

    技术交流,DH讲解.

    前段时间,和群里面的朋友讨论提交包的时候,结果发现Indy被大家狂批,哈哈,后来有人推荐用WinHttp,查看了下MSDN,WinHttp主要是靠system32目录下面的WinHttp.dll这个文件,而它又有2种用法,一个是直接API,复杂些,但是功能强大,另外一个就是直接使用WinHttpRequest这个ActiveX.

    为了使用方便,对WinHttpRequest进行了简单封装,但是感觉不完善,有空补足.还有好多方法没有封装进来,但是留了一个属性property Http:OleVariant read FHttp write FHttp; 这样大家可以直接调用WinHttpRequest.来看看代码:(直接下载)

    unit utWinHttp;
    
    interface
    uses
      SysUtils,Classes,Windows;
    
    const
      request_headers:array[0..14] of string = (
        'Accept','Accept-Encoding','Accept-Language','Cache-Control',
        'CharSet','Connection','Content-Encoding','Content-Language',
        'Content-Type','Date','Expires','From',
        'Referer','UserAgent','Cookie'
      );
    
    const
      WinHttpRequestOption_UserAgentString = $00000000;
      WinHttpRequestOption_URL = $00000001;
      WinHttpRequestOption_URLCodePage = $00000002;
      WinHttpRequestOption_EscapePercentInURL = $00000003;
      WinHttpRequestOption_SslErrorIgnoreFlags = $00000004;
      WinHttpRequestOption_SelectCertificate = $00000005;
      WinHttpRequestOption_EnableRedirects = $00000006;
      WinHttpRequestOption_UrlEscapeDisable = $00000007;
      WinHttpRequestOption_UrlEscapeDisableQuery = $00000008;
      WinHttpRequestOption_SecureProtocols = $00000009;
      WinHttpRequestOption_EnableTracing = $0000000A;
      WinHttpRequestOption_RevertImpersonationOverSsl = $0000000B;
      WinHttpRequestOption_EnableHttpsToHttpRedirects = $0000000C;
      WinHttpRequestOption_EnablePassportAuthentication = $0000000D;
      WinHttpRequestOption_MaxAutomaticRedirects = $0000000E;
      WinHttpRequestOption_MaxResponseHeaderSize = $0000000F;
      WinHttpRequestOption_MaxResponseDrainSize = $00000010;
      WinHttpRequestOption_EnableHttp1_1 = $00000011;
      WinHttpRequestOption_EnableCertificateRevocationCheck = $00000012;
    
      AutoLogonPolicy_Always = $00000000;
      AutoLogonPolicy_OnlyIfBypassProxy = $00000001;
      AutoLogonPolicy_Never = $00000002;
    
      SslErrorFlag_UnknownCA = $00000100;
      SslErrorFlag_CertWrongUsage = $00000200;
      SslErrorFlag_CertCNInvalid = $00001000;
      SslErrorFlag_CertDateInvalid = $00002000;
      SslErrorFlag_Ignore_All = $00003300;
    
      SecureProtocol_SSL2 = $00000008;
      SecureProtocol_SSL3 = $00000020;
      SecureProtocol_TLS1 = $00000080;
      SecureProtocol_ALL = $000000A8;
    
    const
      IStream_GUID:TGUID = '{0000000C-0000-0000-C000-000000000046}';
    
    type
      TCustomWinHttp = class;
      //请求信息类
      TRequest = class(TPersistent)
      private
        FAccept,FAcceptEncoding,FAcceptLanguage:string;
        FCacheControl,FCharSet,FConnection:string;
        FContentEncoding,FContentLanguage,FContentType:string;
        FDate,FExpires,FFrom:string;
        FReferer,FUserAgent:string;
        FCookie:string;
        FCustomHeader:TStringList;
      public
        constructor Create;
        destructor Destroy; override;
      published
        property Accept:string  read FAccept write FAccept;
        property AcceptEncoding:string read FAcceptEncoding write FAcceptEncoding;
        property AcceptLanguage:string read FAcceptLanguage write FAcceptLanguage;
        property CacheControl:string read FCacheControl write FCacheControl;
        property CharSet:string read FCharSet write FCharSet;
        property Connection:string read FConnection write FConnection;
        property ContentEncoding:string read FContentEncoding write FContentEncoding;
        property ContentLanguage:string read FContentLanguage write FContentLanguage;
        property ContentType:string read FContentType write FContentType;
        property Date:string read FDate write FDate;
        property Expires:string read FExpires write FExpires;
        property From:string read FFrom write FFrom;
        property Referer:string read FReferer write FReferer;
        property UserAgent:string read FUserAgent write FUserAgent;
        property Cookie:string read FCookie write FCookie;
        property CustomHeader:TStringList  read FCustomHeader write FCustomHeader;
      end;
      //返回信息类
      TResponse = class(TPersistent)
      private
        FOwner:TCustomWinHttp;
        FHeaderList:TStringList;
        procedure Check;
        function Get_Header(const header_name:string):string;
        function Get_Status:Integer;
        function Get_StatusText:string;
        function Get_ResponseBody:string;
        function Get_HeadersText:string;
      public
        constructor Create(http:TCustomWinHttp);
        destructor Destroy; override;
        property Header[const Name:string]:string  read Get_Header;
        property Status:Integer  read Get_Status;
        property StatusText:string  read Get_StatusText;
        property ResponseBody:string  read Get_ResponseBody;
        property HeadersText:string read Get_HeadersText;
      end;
    
      TCustomWinHttp = class(TComponent)
      private
        FCreated:Boolean;
        FHttp:OleVariant;
        FRequest:TRequest;
        FResponse:TResponse;
        FRequestTime:Integer;
        FOnRequestTimeOut:TNotifyEvent;
    
        procedure SetRequestHeaders;
        procedure Set_Option(idx:Integer;value:OleVariant);
        function Get_Option(idx:Integer):OleVariant;
    
        procedure Set_Redirects(B:Boolean);
        function Get_Redirects:Boolean;
    
        procedure Set_MaxRedirects(N:Integer);
        function Get_MaxRedirects:Integer;
      public
        procedure Abort;
        procedure ClearRequestHeaders;
        function Get(const URL:string):string;overload;
        procedure Get(Const URL:string;res:TStream);overload;
        function Post(const URL:string;Req:TStream):string;overload;
        function Post(const URL,Req:string):string;overload;
        procedure Post(const URL:string;Req,Res:TStream);overload;
        procedure Post(const URL,Req:string;Res:TStream);overload;
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
    
        property Http:OleVariant  read FHttp write FHttp;
        property EnableRedirects:Boolean  read Get_Redirects write Set_Redirects;
        property MaxRedirects:Integer  read Get_MaxRedirects write Set_MaxRedirects;
        property Request:TRequest  read FRequest write FRequest;
        property RequestTime:Integer  read FRequestTime write FRequestTime;
        property OnRequestTimeOut:TNotifyEvent  read FOnRequestTimeOut write FOnRequestTimeOut;
        property Response:TResponse  read FResponse write FResponse;
        property Options[idx:Integer]:OleVariant  read Get_Option write Set_Option;
      end;
    
      TWinHttp = class(TCustomWinHttp)
      published
        property MaxRedirects;
        property EnableRedirects;
        property Request;
        property Response;
        property RequestTime;
        property OnRequestTimeOut;
      end;
    
    implementation
    uses
      ComObj,AxCtrls,ActiveX,Variants;
    
    { TResponse }
    
    procedure TResponse.Check;
    begin
      if FHeaderList.Count = 0 then
        FHeaderList.Text:=FOwner.FHttp.GetAllResponseHeaders;
    end;
    
    constructor TResponse.Create(http:TCustomWinHttp);
    begin
      FOwner:=http;
      FHeaderList:=TStringList.Create;
      FHeaderList.NameValueSeparator:=':';
    end;
    
    destructor TResponse.Destroy;
    begin
      FHeaderList.Free;
      inherited;
    end;
    
    function TResponse.Get_Header(const header_name: string): string;
    begin
      Check;
      Result:=FHeaderList.Values[header_name];
    end;
    
    function TResponse.Get_HeadersText: string;
    begin
      Check;
      Result:=FHeaderList.Text;
    end;
    
    function TResponse.Get_ResponseBody: string;
    begin
      Result:=FOwner.Http.ResponseBody;
    end;
    
    function TResponse.Get_Status: Integer;
    begin
      Result:=FOwner.Http.Status;
    end;
    
    function TResponse.Get_StatusText: string;
    begin
      Result:=FOwner.Http.StatusText;
    end;
    
    { TRequest }
    
    constructor TRequest.Create;
    begin
      inherited;
      FCustomHeader:=TStringList.Create;
    end;
    
    destructor TRequest.Destroy;
    begin
      FCustomHeader.Free;
      inherited;
    end;
    
    { TCustomWinHttp }
    
    procedure TCustomWinHttp.Abort;
    begin
      if FCreated then
        FHttp.Abort();
    end;
    
    procedure TCustomWinHttp.ClearRequestHeaders;
    var
      I,base: Integer;
    begin
      base := Integer(FRequest);
      for I := 0 to 14 do
        PDWORD(base + 4 * (I+1))^:=0;
      FRequest.CustomHeader.Clear;
    end;
    
    constructor TCustomWinHttp.Create(AOwner: TComponent);
    begin
      inherited;
      FRequest:=TRequest.Create;
      FRequest.FCustomHeader.NameValueSeparator:=':';
      FResponse:=TResponse.Create(Self);
      try
        FCreated:=False;
        FHttp:=CreateOleObject('WinHttp.WinHttpRequest.5.1');
        FCreated:=True;
      except
        raise Exception.Create('创建WinHttp失败');
      end;
    
      FRequestTime:=4000;
    end;
    
    destructor TCustomWinHttp.Destroy;
    begin
      Abort;
      FHttp:=0;
      FResponse.Free;
      FRequest.Free;
      inherited;
    end;
    
    function TCustomWinHttp.Get(const URL: string): string;
    var
      ss:TStringStream;
    begin
      Result:='';
      ss:=TStringStream.Create;
      try
        Get(URL,SS);
        Result:=ss.DataString;
      finally
        ss.Free;
      end;
    end;
    
    procedure TCustomWinHttp.Get(const URL: string; res: TStream);
    var
      iu:IUnknown;
      os:TOlestream;
      s:IStream;
      p:OleVariant;
      w:Word;
    begin
      Assert(res<>Nil);
      if Not FCreated then
        Exit;
      //清除已经有的header
      FResponse.FHeaderList.Clear;
      //请求
      try
        FHttp.Open('GET',URL,False);
        SetRequestHeaders;
        FHttp.Send(varEmpty);
        if Not FHttp.WaitForResponse(FRequestTime) then
        begin
          FHttp.Abort;
          if Assigned(FOnRequestTimeOut) then
            FOnRequestTimeOut(Self);
          Exit;
        end;
        P:=FHttp.ResponseStream ;
        W:=VarType(P);
        if w = varUnknown then
        begin
          iu:=IUnknown(P);
          iu.QueryInterface(IStream_GUID,s);
        end;
        if s=nil then
          Exit;
        res.Position:=0;
        os:=TOleStream.Create(s);
        try
          os.Position:=0;
          res.CopyFrom(os,os.Size)
        finally
          os.Free
        end;
      except
      end;
    end;
    
    function TCustomWinHttp.Get_MaxRedirects: Integer;
    begin
      Result:=Get_Option(WinHttpRequestOption_MaxAutomaticRedirects) ;
    end;
    
    function TCustomWinHttp.Get_Option(idx: Integer): OleVariant;
    begin
      Result:=FHttp.Option[idx];
    end;
    
    function TCustomWinHttp.Get_Redirects: Boolean;
    begin
      Result:=FHttp.Option[WinHttpRequestOption_EnableRedirects];
    end;
    
    function TCustomWinHttp.Post(const URL, Req: string): string;
    var
      ss:TStringStream;
    begin
      Result:='';
      SS:=TStringStream.Create;
      try
        Post(URL,Req,SS);
        Result:=ss.DataString;
      finally
        ss.Free;
      end;
    end;
    
    function TCustomWinHttp.Post(const URL: string; Req: TStream): string;
    var
      ss:TStringStream;
      S:string;
    begin
      Assert(Req<>nil);
      ss:=TStringStream.Create;
      try
        Req.Position:=0;
        ss.CopyFrom(Req,Req.Size);
        S:=ss.DataString;
        ss.Clear;
        Post(URL,S,ss);
        Result:=ss.DataString;
      finally
        ss.Free;
      end;
    end;
    
    procedure TCustomWinHttp.Post(const URL: string; Req, Res: TStream);
    var
      ss:TStringStream;
      S:string;
    
    begin
      Assert(Req<>nil);
      ss:=TStringStream.Create;
      try
        Req.Position:=0;
        ss.CopyFrom(Req,Req.Size);
        S:=ss.DataString;
        Post(URL,s,Res)
      finally
        ss.Free;
      end;
    
    end;
    
    procedure TCustomWinHttp.SetRequestHeaders;
    var
      I,dx,base: Integer;
      S:string;
    begin
      base:=Integer(FRequest);
      for I := 0 to 14 do
      begin
        dx:=base + 4 * (I + 1);
        s:=PString(dx)^;
        if s<>'' then
          FHttp.SetRequestHeader(request_headers[I],S);
      end;
      for I := 0 to FRequest.CustomHeader.Count - 1 do
        FHttp.SetRequestHeader(FRequest.CustomHeader.Names[I],
                FRequest.CustomHeader.ValueFromIndex[I]
        );
    
    end;
    
    procedure TCustomWinHttp.Set_MaxRedirects(N: Integer);
    begin
      Set_Option(WinHttpRequestOption_MaxAutomaticRedirects,N);
    end;
    
    procedure TCustomWinHttp.Set_Option(idx: Integer; value: OleVariant);
    begin
      FHttp.Option[idx]:=value;
    end;
    
    procedure TCustomWinHttp.Set_Redirects(B: Boolean);
    begin
      Set_Option(WinHttpRequestOption_EnableRedirects,B);
    end;
    
    procedure TCustomWinHttp.Post(const URL, Req: string; Res: TStream);
    var
      s:IStream;
      os:TOleStream;
      p:OleVariant;
    begin
      Assert(Res<>Nil);
      if Not FCreated then
        Exit;
      FResponse.FHeaderList.Clear;
      try
        FHttp.Open('POST',URL,False);
        SetRequestHeaders;
        FHttp.SetRequestHeader('Content-Length',IntToStr(Length(Req)));
        FHttp.Send(Req);
        if Not FHttp.WaitForResponse(FRequestTime) then
        begin
          FHttp.Abort;
          if Assigned(FOnRequestTimeOut) then
            FOnRequestTimeOut(Self);
          Exit;
        end;
        P:=FHttp.ResponseStream;
        if VarType(P) = varUnknown then
          IUnknown(P).QueryInterface(IStream_GUID,S);
        if s=nil then
          Exit;
        os:=TOleStream.Create(s);
        try
          Res.Position:=0;
          os.Position:=0;
          Res.CopyFrom(os,os.Size);
        finally
          os.Free;
        end;
      except
      end;
    end;
    
    end.


    简单用法,表单提交来登录人人网:

    type
      TForm3 = class(TForm)
        btn1: TButton;
        procedure FormCreate(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure btn1Click(Sender: TObject);
      private
        { Private declarations }
        Http:TWinHttp;
      public
        { Public declarations }
      end;
    
    var
      Form3: TForm3;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm3.btn1Click(Sender: TObject);
    var
      s:string;
    begin
      //清空之前的header
      Http.ClearRequestHeaders;
      //设置自己的header ,两种方法都可以
      //POST时候这个必须设置成这样
      Http.Request.ContentType:='application/x-www-form-urlencoded';
    //  Http.Request.CustomHeader.Add('Content-Type: application/x-www-form-urlencoded');
      S:=Http.Post('http://www.renren.com/PLogin.do',
      'email=huangjacky@163.com&password=密码&origURL=http%3A%2F%2Fwww.renren.com%2FHome.do&domain=renren.com');
      //html代码
      ShowMessage(S);
      //返回的header
      ShowMessage(Http.Response.HeadersText);
      //状态
      ShowMessageFmt('Code:%D,Text:%S',
          [Http.Response.Status,Http.Response.StatusText]
        );
    end;
    
    procedure TForm3.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      Http.Free;
    end;
    
    procedure TForm3.FormCreate(Sender: TObject);
    begin
      Http:=TWinHttp.Create(Self);
      //禁止转向
      Http.EnableRedirects:=False;
    end;

    再来个下载文件的例子:

    procedure TForm3.btn2Click(Sender: TObject);
    var
      S:TFileStream;
    begin
      s:=TFileStream.Create('C:\11.rar',fmCreate);
      Http.Get('https://files.cnblogs.com/huangjacky/Delphi.Distiller.v1.83.rar',s);
      s.Free;
    end;


    我是DH,吃饭去了

  • 相关阅读:
    Java
    Java
    Java
    Java
    Java
    Hang Gliding线段树
    Biggest Number深搜
    2021年暑假康复性训练(Codeforces Round #731 (Div. 3))全题解
    Python GUI tkinter 随机生成题目
    ModuleNotFoundError: No module named ‘exceptions‘ 情况解决
  • 原文地址:https://www.cnblogs.com/huangjacky/p/1635830.html
Copyright © 2011-2022 走看看