以delphi xe2 自带indy(10.5.8.0)组件为例,分享实战中遇到的问题及解决方法。
Idhttp 重要属性
HTTPOptions := [];
属性设为空,禁止idhttp自动为post的TStringList参数编码,因为自动编码使用的是HttpApp单元下的HttpEncode,
但此函数有误,未将+,$,@这3个符号编成UrlCode。请自行改造此函数然后使用。
HTTPOptions := [hoNoParseMetaHTTPEquiv];
当遇到Get某个网页,idhttp一直会卡住的时候,请尝试此值。
提供一个会卡住的网址给大家测试:http://www.bf35.com/Company/Detail/23284.html
此网址来之不易,请善加保存!哈哈!
Request.RawHeaders.FoldLength := 8192;
参数头的总长度限制,如果post的TStringList参数过长,请加大此值。否则,超长部分将不会被post。
FIdCookieMgr := TIdCookieMgr.Create(self); //TIdCookieMgr
CookieManager := FIdCookieMgr;
AllowCookies := true;
TIdCookieMgr是我改进了的TIdCookieManager,增加了保存Cookie与加载Cookie的方法。后面详细写出。
IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(self);
此为Https功能必备,它需要两个文件 libeay32.dll和ssleay32.dll,
这两个文件在阿里旺旺的安装目录里能够找到。大家不必满世界找了。
Request.AcceptEncoding := ‘gzip‘;
在Get与Post的时候,告诉服务器,请把数据压缩后再传给我。
Idhttp自带的解压缩功能是错误的,需要自己去下载一个 Zlib 库,然后自己解压缩。见后面。
idhttp自带的解utf-8编码也是错误的,也需要自己手动解码。见后面
HandleRedirects := true;
ProtocolVersion := pv1_1;
ReadTimeout := 5000;
ConnectTimeout := 5000;
RedirectMaximum := 5;
Request.UserAgent := sUserAgent2;
Request.Accept := sAccept;
这几个属性,不再解释。
TIdCookieMgr 实现的功能
此类从TIdCookieMgr继承而来,下面是重点。
function TIdCookieMgr.GetCookieList: TStringList;
var
C: Tcollectionitem;
begin
result := TStringList.Create;
for C in CookieCollection do
result.add((C as TIdCookie).CookieText);
end;
这是当获取到Cookie后,如何取得所有Cookie的文本。这很简单。
下面讲如何把保存后的Cookie文本加载回去
procedure TIdCookieMgr.SetCurCookies(const Value: string);
var
StrLst: TStringList;
C: TIdCookie;
uri: TIdURI;
s, t: string;
begin
StrLst := TStringList.Create;
uri := TIdURI.Create;
try
StrLst.Text := Value;
CookieCollection.Clear;
for s in StrLst do
begin
C := CookieCollection.add;
CookieCollection.AddCookie(C, uri);
C.ParseServerCookie(s, uri);
C.Domain := GetStrBetween(s, ‘Domain=‘, ‘;‘);
C.Path := GetStrBetween(s, ‘Path=‘, ‘;‘);
//GetStrBetween 请自己去实现一个。
t := GetStrBetween(s, ‘Expires=‘, ‘GMT‘) + ‘GMT‘;
C.Expires := CookieStrToLocalDateTime(t);
end;
finally
uri.Free;
StrLst.Free;
end;
end;
GetHtmlAfterOperateIdhtpp 这个函数重要,请copy下来,等会要用
用于解压Gzip,解码utf8
1 function GetHtmlAfterOperateIdhttp(AIdhttp: TIdHTTP; AStream: TStream): string; 2 var 3 BSize: Int64; 4 BOutStream: TMemoryStream; 5 TempStream: TMemoryStream; 6 rS: RawByteString; //注意这个格式 7 s: string; 8 BIsUtf8: Boolean; 9 begin 10 BSize := AStream.Size; 11 12 BOutStream := TMemoryStream.Create; 13 try 14 if BSize > 0 then 15 begin 16 17 if PosEx(‘GZIP‘, UpperCase(AIdhttp.Response.ContentEncoding)) > 0 then 18 begin 19 AStream.Position := 0; ZDecompressStream2(AStream, BOutStream, 31); //这个函数在Zlib库的 ZLibEx.pas中,请自行去下载. 31 这个参数,是搜了很多资料才找到的,不知道为什么。免费送给大家用了。 21 TempStream := BOutStream; 22 end 23 else 24 TempStream := TMemoryStream(AStream); 25 26 BSize := TempStream.Size; 27 SetLength(rS, BSize); 28 TempStream.Position := 0; 29 TempStream.ReadBuffer(rS[1], BSize); 30 31 s := string(rS); 32 33 BIsUtf8 := PosEx(‘UTF-8‘, UpperCase(AIdhttp.Response.CharSet)) > 0; 34 35 BIsUtf8 := BIsUtf8 or (PosEx(‘charset="utf-8"‘, s) > 0); 36 BIsUtf8 := BIsUtf8 or (PosEx(‘charset=utf-8‘, s) > 0); //判断代码是不是Utf8 不是很严谨,请自动修改后使用 37 38 if PosEx(‘GBK‘, UpperCase(AIdhttp.Response.CharSet)) > 0 then 39 begin 40 BIsUtf8 := false; 41 end; 42 43 if BIsUtf8 then 44 result := UTF8ToString(rS) //注意rS的类型 45 else 46 result := s; 47 48 end 49 finally 50 BOutStream.Free; 51 end; 52 53 end;
下面给出三个操作idhttp的函数,用它们就很方便了.
function IdhttpGet(AIdhttp: TIdHTTP; const AUrl: string; var AHtml: string): Boolean; var BStrStream: TMemoryStream; begin AHtml := ‘‘; BStrStream := TMemoryStream.Create; try try AIdhttp.Get(AUrl, BStrStream); AHtml := GetHtmlAfterOperateIdhttp(AIdhttp, BStrStream); result := true; except on e: Exception do begin result := false; AHtml := e.Message; end; end; finally BStrStream.Free; end; end; function IdhttpPost(AIdhttp: TIdHTTP; AStrList: TStringList; const AUrl: string; var AHtml: String): Boolean; overload; var BStrStream: TMemoryStream; begin result := true; AHtml := ‘‘; BStrStream := TMemoryStream.Create; try try AIdhttp.Post(AUrl, AStrList, BStrStream); AHtml := GetHtmlAfterOperateIdhttp(AIdhttp, BStrStream); except on e: Exception do begin AHtml := e.Message; result := false; end; end; finally BStrStream.Free; end; end; function IdhttpPost(AIdhttp: TIdHTTP; AIdMul: TIdMultiPartFormDataStream; const AUrl: string; var AHtml: string) : Boolean; overload; var BStrStream: TMemoryStream; begin result := true; AHtml := ‘‘; BStrStream := TMemoryStream.Create; try try AIdhttp.Post(AUrl, AIdMul, BStrStream); AHtml := GetHtmlAfterOperateIdhttp(AIdhttp, BStrStream); except on e: Exception do begin AHtml := e.Message; result := false; end; end; finally BStrStream.Free; end; end;
别急,还有。如何手工给post参数编码
请自己改造HttpEncode函数,可以是像我这样子的.
function HttpEncodeX(const AStr: string): string;
var
s: string;
begin
s := String(HttpEncode(AnsiString(UTF8Encode(AStr))));
//通常来说,如果参数有中文,是先编成Utf8再urlEncode的。请看清后再使用.
s := ReplaceAll(s, ‘+‘, ‘%20‘); //此函数请去网上搜一个.
s := ReplaceAll(s, ‘$‘, ‘%24‘);
Result := ReplaceAll(s, ‘@‘, ‘%40‘);
end;
编码方法:
var
BStrs:TSTringList;
begin
BStrs:=TStringlist.Create;
BStrs.add(‘name=‘+HttpEncodeX(‘晓不得abc‘));
BStrs.add( HttpEncodeX(‘na$me‘)+‘=‘+HttpEncodeX(‘晓不得abc‘));
//切记,这里的等号用原型,不要编码。idhttp会自动把等号翻译成 & 放在请求头中.
end;
好了,over,祝大家编的外挂功能越来越好用!