在HTTP请求中,get方法是默认的,但在URL地址长度是有限的,请求方法能传送的数据也是有限的,一般get方法传递的数据不能大于2KB,当get请求方法传递的数据长度不能满足需求时,就需要采用另一种请求方法post,读取post方法传递过来的数据时,需要采用form方法来获取;post方法提交请求时,地址栏看不到传送过来的参数数据,更加有利于页面的安全,所以一般情况采用post方法传送页面数据。post传送的数据量较大,一般被默认为不受限制。但理论上,IIS5中最大量为100KB。

 

由于目前后台的接口采用的是Servlet来响应HTTP请求,所有的请求也必须遵循javaee servlet的规范。在Servlet 2.3及以后的版本中,已经默认增加了Filter处理,所以如果要在Servlet中的request对象能够自动读取post form的数据要满足以下条件:

1.request是HTTP/HTTPS request 
2.HTTP method是POST。 
3.content type是application/x-www-form-urlencoded。 
  
在Delphi中有很多实体类可以实现HTTP请求,但比较方便的就是使用THTTPReqResp,比较原始的TIdHTTP类(需要自行管理cookie的值)。 
因为THTTPReqResp自动封装了请求的细节处理,可以省去很多麻烦,特别是对Cookie的管理,但该对象发送请求的时候Header默认的content-type="text/xml" 所以要修改请求头的content-type才可以可以服务器端接收到post的数据。 
要实现自定义Header需要在OnBeforePost事件中重定义Header信息 
FHttpReq.OnBeforePost := BeforePost; 
通过替换的方式把原来的content-type改为想要的结果: 
HttpAddRequestHeaders(Data, PChar(csCustomHeader), Length(csCustomHeader), HTTP_ADDREQ_FLAG_REPLACE); 
  
详细的代码如下: 
  
{ ------------------------------------------------------------------------------- 
 过程名: TDataSync.ModPassword 
 参数: oldPass:原密码 
 newPass:新密码 
 返回值: true表示成功;false表示失败,失败时可以通过GetLastError获得错误信息 
 ------------------------------------------------------------------------------- } 
function TDataSync.ModPassword(oldPass, newPass: string): boolean; 
var 
 url, content: string; 
begin 
 result := false; 
 try 
 url := Format(URL_AltPass, [FWebSite, oldPass, newPass]); 
 content := GetResponseContent(url); 
 result := GetResponseState(content); 
 except 
 SetLastError('网络故障,更改用户密码失败!'); 
 end; 
end; 
  
procedure TDataSync.BeforePost(const HTTPReqResp: THTTPReqResp; Data: Pointer); 
const 
 csCustomHeader = 
 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8'; 
begin 
 HttpAddRequestHeaders(Data, PChar(csCustomHeader), Length(csCustomHeader), 
 HTTP_ADDREQ_FLAG_REPLACE); 
end; 
  
function TDataSync.GetResponseContentPost(url: string; 
 const DataMsg: String): string; 
var 
 strStream, strSend: TStringStream; 
begin 
 result := ''; 
 strStream := TStringStream.Create('', TEncoding.UTF8); 
 strSend := TStringStream.Create(DataMsg, TEncoding.UTF8); 
 try 
 FHttpReq.url := url; 
 FHttpReq.OnBeforePost := BeforePost; 
 FHttpReq.Execute(strSend, strStream); 
 result := strStream.DataString; 
 except 
 SetLastError('无效数据包,可能网络故障!'); 
 end; 
 strStream.Free; 
 strSend.Free; 
end; 
  
// 重载简单接口调用 
function TDataSync.GetResponseContent(url: string): string; 
begin 
 result := GetResponseContentPost(url, ''); 
end; 
  
function TDataSync.GetResponseState(strResponse: string): boolean; 
var 
 code: string; 
 jo: ISuperObject; 
begin 
 result := false; 
 if strResponse = '' then 
 begin 
 SetLastError('服务端无响应当前服务请求!'); 
 exit; 
 end; 
  
 jo := TSuperObject.ParseString(PWideChar(strResponse), false); 
 if jo = nil then 
 exit; 
  
 if jo['flag'] = nil then 
 begin 
 SetLastError('未知的服务响应!'); 
 exit; 
 end; 
 code := jo['flag'].AsString; 
 result := (code = QUERY_SUCC) or (code = OP_SUCC); 
 if jo['info'] <> nil then 
 SetLastError(jo['info'].AsString) 
 else 
 begin 
 if code = 'EMPLOYEECODE_EXIST' then 
 SetLastError('工号已存在') 
 else if code = 'EXCEED_MORE_THAN_LIMIT' then 
 SetLastError('超过公司的总人数') 
 else 
 SetLastError(code); 
 end; 
end; 
  
{ ------------------------------------------------------------------------------ } 
constructor TDataSync.Create(AOwner: TSWObject; url, dicURL: string); 
begin 
 inherited Create(AOwner); 
 FWebSite := url; 
 FDicSite := dicURL; 
  
 FHttpReq := THTTPReqResp.Create(AOwner); 
 FHttpReq.UseUTF8InHeader := true; 
end; 
  
destructor TDataSync.Destroy(); 
begin 
 FHttpReq.Free; 
 inherited; 
end;