使用 THttpClient Post时发送指定编码的文本内容

栏目: 编程语言 · 发布时间: 7年前

内容简介:使用 THttpClient Post时发送指定编码的文本内容

THttpClient 是 Delphi/C++ Builder 新引入的一个 HTTP/HTTPS 协议客户端的封装,相当好用。我现在已经基本上不使用 libcurl 了,它已经能满足我绝大多数情况下的 HTTP 操作请求。

不过,最近遇到了一点小问题,我们先看 Post 函数的声明:

Delphi/Pascal

/// <summary>Post a raw file without multipart info</summary>
    function Post(const AURL: string; const ASourceFile: string; const AResponseContent: TStream = nil; const AHeaders: TNetHeaders = nil): IHTTPResponse; overload;
    /// <summary>Post TStrings values adding multipart info</summary>
    function Post(const AURL: string; const ASource: TStrings; const AResponseContent: TStream = nil;
      const AEncoding: TEncoding = nil; const AHeaders: TNetHeaders = nil): IHTTPResponse; overload;
    /// <summary>Post a stream without multipart info</summary>
    function Post(const AURL: string; const ASource: TStream; const AResponseContent: TStream = nil;
      const AHeaders: TNetHeaders = nil): IHTTPResponse; overload;
    /// <summary>Post a multipart form data object</summary>
    function Post(const AURL: string; const ASource: TMultipartFormData; const AResponseContent: TStream = nil;
      const AHeaders: TNetHeaders = nil): IHTTPResponse; overload;
 /// <summary>Post a raw file without multipart info</summary>
    function Post(const AURL: string; const ASourceFile: string; const AResponseContent: TStream = nil; const AHeaders: TNetHeaders = nil): IHTTPResponse; overload;
    /// <summary>Post TStrings values adding multipart info</summary>
    function Post(const AURL: string; const ASource: TStrings; const AResponseContent: TStream = nil;
      const AEncoding: TEncoding = nil; const AHeaders: TNetHeaders = nil): IHTTPResponse; overload;
    /// <summary>Post a stream without multipart info</summary>
    function Post(const AURL: string; const ASource: TStream; const AResponseContent: TStream = nil;
      const AHeaders: TNetHeaders = nil): IHTTPResponse; overload;
    /// <summary>Post a multipart form data object</summary>
    function Post(const AURL: string; const ASource: TMultipartFormData; const AResponseContent: TStream = nil;
      const AHeaders: TNetHeaders = nil): IHTTPResponse; overload;

这是 THttpClient 的 Post 的几个重载,如果我要直接提交一个 JSON 或 XML 字符串到服务器端,上面的第 1 种重载要求先保存到文件再提交,第 2 种重载要求的是一个 TStrings 对象,看起来很有戏,第三个重载是投寄一个流进去,看起来也有戏,第四种重载明显就是我们需要的了。

好吧,然后我们进入第 2 种重载的源码,发现了什么?

Delphi/Pascal

LParams := '';
  for I := 0 to ASource.Count - 1 do
  begin
    Pos := ASource[I].IndexOf('=');
    if Pos > 0 then
      LParams := LParams + ASource[I].Substring(0, Pos) + '=' + TURI.URLEncode(ASource[I].Substring(Pos + 1), True) + '&';
  end;
  LParams := LParams.Substring(0, LParams.Length - 1); // Remove last &
LParams := '';
  for I := 0 to ASource.Count - 1 do
  begin
    Pos := ASource[I].IndexOf('=');
    if Pos > 0 then
      LParams := LParams + ASource[I].Substring(0, Pos) + '=' + TURI.URLEncode(ASource[I].Substring(Pos + 1), True) + '&';
  end;
  LParams := LParams.Substring(0, LParams.Length - 1); // Remove last &

也就是说,它传递的是实际上是 Name -Value 值对,没配对的直接忽略掉了。显然也不符合我们的要求,可以被 Pass 掉了。剩下的唯一选择就是传递一个流进去。

好了,QJSON 和 QXML 都提供了保存到流里的支持,所以创建一个临时的内存流,保存下来后做为参数传递进去,用完释放就 OK 了。如果嫌不够直观,还可以用 QMacros 来用模板替换的方式来替换,效率一样杠杠的。下面是一个简单的例子(用 THttpClient 用轻码云发送模板短信):

Delphi/Pascal

var
  AResponse: IHttpResponse;
  AUrl: String;
  AMacros: TQMacroManager;
  AReply, AItem: TQJson;
  ATimeStamp: String;
  AStream: TStringStream;
const
  AVerifyUrl
    : String =
    '#protocol#://api.qingmayun.com/#SoftVersion#/accounts/#accountSid#/SMS/templateSMS?'
    + 'sig=#sig#&timestamp=#timestamp#';
  APostContent: String = '{'#13#10 + '"templateSMS": {'#13#10 +
    '    "appId": "#appId#",'#13#10 + '    "templateId": "#templateId#",'#13#10
    + '    "to": "#to#",'#13#10 + '    "param": "#param#"'#13#10 +
    ' }'#13#10 + '}';
  function CalcSign: String;
  var
    S: String;
    ADigest: TQMD5Digest;
  begin
    S := AccountId + AuthToken + ATimeStamp;
    ADigest := MD5Hash(S);
    Result := BinToHex(@ADigest, SizeOf(ADigest), true);
  end;

begin
  Result := False;
  AMacros := TQMacroManager.Create;
  AStream := TStringStream.Create('', TEncoding.UTF8, False);
  try
    ATimeStamp := FormatDateTime('yyyymmddhhnnss', Now);
    AMacros.Push('protocol', 'https');
    AMacros.Push('SoftVersion', '20141029');
    AMacros.Push('accountSid', AccountId);
    AMacros.Push('appId', AppId);
    AMacros.Push('templateId', TemplateId);
    AMacros.Push('to', APhoneNum);
    AMacros.Push('param', ACode + ',30');
    AMacros.Push('sig', CalcSign);
    AMacros.Push('timestamp', ATimeStamp);
    AUrl := AMacros.Replace(AVerifyUrl, '#', '#');
    FHttpClient.Accept := 'application/json';
    FHttpClient.ContentType := 'application/json;charset=utf-8';
    AStream.WriteString(AMacros.Replace(APostContent, '#', '#',
      MRF_IN_DBL_QUOTER));
    AStream.Position := 0;
    AResponse := FHttpClient.Post(AUrl, AStream);
    if Assigned(AResponse) then
    begin
      if AResponse.StatusCode = 200 then
      begin
        AReply := TQJson.Create;
        try
          if AReply.TryParse(AResponse.ContentAsString()) then
          begin
            FLastError := AReply.ValueByPath('result.respCode', '');
            if FLastError = '00000' then
              Result := true;
          end;
        finally
          FreeAndNil(AReply);
        end;
      end
      else
        FLastError := IntToStr(AResponse.StatusCode);
    end
    else
      FLastError := '-1';
  finally
    FreeAndNil(AMacros);
  end;
var
  AResponse: IHttpResponse;
  AUrl: String;
  AMacros: TQMacroManager;
  AReply, AItem: TQJson;
  ATimeStamp: String;
  AStream: TStringStream;
const
  AVerifyUrl
    : String =
    '#protocol#://api.qingmayun.com/#SoftVersion#/accounts/#accountSid#/SMS/templateSMS?'
    + 'sig=#sig#&timestamp=#timestamp#';
  APostContent: String = '{'#13#10 + '"templateSMS": {'#13#10 +
    '    "appId": "#appId#",'#13#10 + '    "templateId": "#templateId#",'#13#10
    + '    "to": "#to#",'#13#10 + '    "param": "#param#"'#13#10 +
    ' }'#13#10 + '}';
  function CalcSign: String;
  var
    S: String;
    ADigest: TQMD5Digest;
  begin
    S := AccountId + AuthToken + ATimeStamp;
    ADigest := MD5Hash(S);
    Result := BinToHex(@ADigest, SizeOf(ADigest), true);
  end;
 
begin
  Result := False;
  AMacros := TQMacroManager.Create;
  AStream := TStringStream.Create('', TEncoding.UTF8, False);
  try
    ATimeStamp := FormatDateTime('yyyymmddhhnnss', Now);
    AMacros.Push('protocol', 'https');
    AMacros.Push('SoftVersion', '20141029');
    AMacros.Push('accountSid', AccountId);
    AMacros.Push('appId', AppId);
    AMacros.Push('templateId', TemplateId);
    AMacros.Push('to', APhoneNum);
    AMacros.Push('param', ACode + ',30');
    AMacros.Push('sig', CalcSign);
    AMacros.Push('timestamp', ATimeStamp);
    AUrl := AMacros.Replace(AVerifyUrl, '#', '#');
    FHttpClient.Accept := 'application/json';
    FHttpClient.ContentType := 'application/json;charset=utf-8';
    AStream.WriteString(AMacros.Replace(APostContent, '#', '#',
      MRF_IN_DBL_QUOTER));
    AStream.Position := 0;
    AResponse := FHttpClient.Post(AUrl, AStream);
    if Assigned(AResponse) then
    begin
      if AResponse.StatusCode = 200 then
      begin
        AReply := TQJson.Create;
        try
          if AReply.TryParse(AResponse.ContentAsString()) then
          begin
            FLastError := AReply.ValueByPath('result.respCode', '');
            if FLastError = '00000' then
              Result := true;
          end;
        finally
          FreeAndNil(AReply);
        end;
      end
      else
        FLastError := IntToStr(AResponse.StatusCode);
    end
    else
      FLastError := '-1';
  finally
    FreeAndNil(AMacros);
  end;

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Spring in Action

Spring in Action

Craig Walls / Manning Publications / 2011-6-29 / USD 49.99

Spring in Action, Third Edition has been completely revised to reflect the latest features, tools, practices Spring offers to java developers. It begins by introducing the core concepts of Spring and......一起来看看 《Spring in Action》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具