delphi 10.3实现TNetHTTPClient 异步 POST 另类实现返回附加标记及Unicode 编码与解码

夜郎王子
2020-08-26

unit HOHttpAsynPost;


interface


Uses System.Classes,Winapi.Windows,System.SysUtils,IHOHttpAsynPost

     ,uLogger,System.Net.URLClient, System.Net.HttpClient, System.Net.HttpClientComponent

     ,strUtils;


type   TPostResProc    = procedure(Buff:PWIdeChar;MsgID:PWIdeChar)   of object;//定义回调

  THONetHttp=class(TNetHTTPClient)

   public

    msgid:String;

    PostRes:TPostResProc;

   constructor Create(AOwner: TComponent); // override;

    destructor Destroy; // override;

   procedure   RequestCompleted(const Sender: TObject; const AResponse: IHTTPResponse);

   procedure RequestError(const Sender: TObject; const AError: string);

  end;


procedure HttpAsynPost(Url:widestring;Buff:Pwidechar;PostRes1:TPostResProc;Msgid1:widestring;ConnectionTimeout1: Integer;ResponseTimeout1: Integer); stdcall;


function   GetDllPath: string;

implementation


procedure HttpAsynPost(Url:widestring;Buff:Pwidechar;PostRes1:TPostResProc;Msgid1:widestring;ConnectionTimeout1: Integer;ResponseTimeout1: Integer); stdcall;

var

  Nhttp:THONetHttp;

  Stream:TStringStream;

  Buffer:Widestring;

  function ChineseToUnicode(Inputstr: string): string;

var //Unicode编码

  Wide_Str: WideString;

  WideChar_Byte_Array: Array of Byte;

  s2:string;

  i:integer;

begin

  Wide_Str := Inputstr;//转为Unicode

  //字节数 = Unicode字数 * Unicode单字的字节数

  SetLength(WideChar_Byte_Array, Length(Wide_Str) * sizeof(WideChar));

  //复制到字节数组当中

  Move(PChar(Wide_Str)^, WideChar_Byte_Array[0], Length(Wide_Str) * sizeof(WideChar));

  i:=0;

  while I<High(WideChar_Byte_Array) do

  begin

    if WideChar_Byte_Array[I+1]=0 then

       S2:=S2+char(WideChar_Byte_Array[I])

    else

    S2:=S2+'\u'+inttohex(WideChar_Byte_Array[I+1])+inttohex(WideChar_Byte_Array[I]);

    I:=I+2;

  end;

  result:=s2;

  //释放字节数组

  SetLength(WideChar_Byte_Array, 0);

  WideChar_Byte_Array := Nil;

end;

Begin

try

   Buffer:=Buff;

   Buffer:=ChineseToUnicode(Buffer);

   log.WriteLog('['+Msgid1+']'+Url+ #13#13+Buffer);

   Stream:=TStringStream.Create;

   Stream.WriteString( Buffer);

   Stream.Position:=0;

   Nhttp:=THONetHttp.Create(Nil);//每次调用启用一个新的THONetHttp

   with Nhttp do

   begin


      AcceptCharSet := 'utf-8';

      AcceptEncoding := '65001';

      AcceptLanguage := 'zh-CN';

      ContentType := 'application/json'; //text/html

      UserAgent := 'CNHIS URI Client/1.0';

      Asynchronous:=True;

     Nhttp.OnRequestCompleted:=RequestCompleted;

     nhttp.OnRequestError:=RequestError;

     ConnectionTimeout :=ConnectionTimeout1;

     ResponseTimeout := ResponseTimeout1;

     msgid:=Msgid1;//附加标记

     PostRes:=PostRes1;//注册回调

     Post(Url,Stream);


   end;

EXcept

  ON E:Exception do

  Begin


    log.WriteLog('['+Msgid1+']发送出错:' + e.Message );


  End;

end;

end;







function   GetDllPath: string;

var

  ModuleName: string;

begin

  SetLength(ModuleName, 255);

    //取得Dll自身路径

  GetModuleFileName(HInstance, PChar(ModuleName), Length(ModuleName));

  Result := ExtractFileDir(PChar(ModuleName));


end;


{ TNetHttp }


constructor THONetHttp.Create(AOwner: TComponent);

begin

   inherited Create(AOwner);

end;


destructor THONetHttp.Destroy;

begin

   inherited;

end;


procedure THONetHttp.RequestCompleted(const Sender: TObject; const AResponse: IHTTPResponse);

Var

Buff:String;

Buffer:PwideChar;

Msgid1:PwideChar;

i:integer;

begin //异步返回

try

   Msgid1:=@THONetHttp(sender).msgid[1];

   Buff:=AResponse.ContentAsString(TEncoding.UTF8);

  if Buff='' then

      Buff:='[错误信息]服务器返回空';

   Buffer:=@Buff[1];

   log.WriteLog('['+Msgid1+']' +'API返回:'+Buffer);

   if assigned(THONetHttp(sender).PostRes) then

   Begin

    THONetHttp(sender).PostRes(Buffer,Msgid1);//回调时带上MSGID实现调用方的唯一处理,含同步等待等接口不能返回对等唯一ID时的需求的实现

   End;

   THONetHttp(sender).Free;//释放

EXcept

  ON E:Exception do

  Begin

    log.WriteLog('['+Msgid1+']'+'处理返回值出错:' + e.Message);

  End;

end;

end;


procedure THONetHttp.RequestError(const Sender: TObject; const AError: string);

Var

Buff:String;

Buffer:PwideChar;

Msgid1:PwideChar;

i:integer;

begin

try

   Msgid1:=@THONetHttp(sender).msgid[1];

   Buff:='[错误信息]'+AError;

   log.WriteLog('['+Msgid1+']'+Buff);

   if assigned(THONetHttp(sender).PostRes) then

   Begin

    Buffer:=@Buff[1];

    THONetHttp(sender).PostRes(Buffer,Msgid1);

   End;

   THONetHttp(sender).Free;

EXcept

  ON E:Exception do

  Begin

    log.WriteLog('['+Msgid1+']'+'处理错误信息出错:' + e.Message);

  End;

end;

end;


initialization


Log.SetLogDir(GetDllPath + '\..\Log\', 'Plugin.HttpAsynPost');



finalization

end.


阅读842