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,吃饭去了

  • 相关阅读:
    Eclipse安装Hadoop插件
    (转)Ubuntu14.0.4中hadoop2.4.0伪分布模式配置
    Hadoop--DataNode无法启动
    启动与关闭hadoop
    hadoop中执行命令时发生错误
    strings命令
    Deriving data from ElasticSearch Engine
    elasticsearch data importing
    reading words in your computer and changing to female voice, linux festival text2wave saving wav files
    DDNS client on a Linux machine
  • 原文地址:https://www.cnblogs.com/huangjacky/p/1635830.html
Copyright © 2011-2022 走看看