IdHttp 资料

http://blog.csdn.net/delphizhou/article/details/3085704

IdHttp 资料 网上找了些不过很不好找.今天找了些收藏在一起.以便他人查阅,

 

idhttp上传

 

先引用MsMultiPartFormData单元,在f:/code/delphi/component/下


通用的函数
{*******************************************************************************
使用INDY IDHTTP上传
idHTTP   TIdHTTP
URL      URL of upload file address
FiledName,FieldValues,FieldnFiles,FieldvFiles array of string
returnvalue 用于比较返回值以比较返回正确性
}
function HttpUpload(idHTTP:TIdHTTP;URL:String;FieldNames, FieldValues,
FieldnFiles, FieldvFiles: array of string;ReturnValue:String='1'):Boolean;
var
responseStream: TStringStream;
mpfSource: TMsMultiPartFormDataStream;

i:integer;
n, v:String;
begin
result:=false;

mpfSource := TMsMultiPartFormDataStream.Create;
responseStream := TStringStream.Create('');
try

    idHTTP.Request.ContentType := mpfSource.RequestContentType;
    //解析字段名
    for i := Low(FieldNames) to High(FieldNames) do
    begin
      n := FieldNames[i];
      v := FieldValues[i];
      mpfSource.AddFormField(n, v);
    end;

    //解析需要上传的文件名和文件地址
    for i := Low(FieldnFiles) to High(FieldnFiles) do
    begin
      n := FieldnFiles[i];
      v := FieldvFiles[i];
      mpfSource.AddFile(n,v, 'Content-Type: image/pjpeg');
    end;
    mpfSource.PrepareStreamForDispatch;
    mpfSource.Position := 0;
    try
      idHTTP.Post(URL, mpfSource, responseStream);
      result:=returnvalue=trim(responseStream.DataString);
    except

    end;
finally
    mpfSource.free;
    responseStream.free;
end;
end;

调用方法:

HttpUpload(idhttp1,'http://192.168.50.98:9999/tmpuploadpic.do',['username','resource'],['oranje','gocom'],['file'],['c:/123.bmp'],'1');


procedure TForm1.TntBitBtn1Click(Sender: TObject);
const
BaseURL   = 'http://192.168.50.98:9999/tmpuploadpic.do';      //论坛所在地址
var
responseStream: TStringStream;
mpfSource: TMsMultiPartFormDataStream;
a:String;
begin
mpfSource := TMsMultiPartFormDataStream.Create;
responseStream := TStringStream.Create('');
try

    IdHTTP.Request.ContentType := mpfSource.RequestContentType;
    mpfSource.AddFormField('username', 'oranje');
    mpfSource.AddFormField('resource', 'xxxx');
    //mpfSource.AddFormField('file', 'C:/Documents and Settings/Administrator/My Documents/GoCom/image/wow3/Water lilies.jpg');
    mpfSource.AddFile('file','C:/Documents and Settings/Administrator/My Documents/GoCom/image/wow3/Water lilies.jpg', 'Content-Type: image/pjpeg');
    mpfSource.PrepareStreamForDispatch;
    mpfSource.Position := 0;
    try
      IdHTTP.Post(BaseURL, mpfSource, responseStream);
      //这里a是返回值,即页面上打出来的值
      a:=trim(responseStream.DataString);
      showmessage(a);
    except

    end;

finally
    mpfSource.free;
    responseStream.free;

 

=============================================================================================

 

idHTTP最简洁的修改和取得Cookie例子

 

procedure TForm1.Button1Click(Sender: TObject);
var
HTTP: TidHTTP;
html, s: string;
i: integer;
begin
HTTP := TidHTTP.Create(nil);
try
HTTP.HandleRedirects := True;
HTTP.AllowCookies := True;
HTTP.Request.CustomHeaders.Values['Cookie'] := 'abcd';//修改Cookie 抓包可见
html := HTTP.Get('http://www.baidu.com/');

s := 'Cookies: ';
if HTTP.CookieManager.CookieCollection.Count > 0 then
for i := 0 to HTTP.CookieManager.CookieCollection.Count - 1 do
s := s + HTTP.CookieManager.CookieCollection.Items[i].CookieText;
Memo1.Lines.Add(s);//取得Cookie
finally
FreeAndNil(HTTP);
end;
end;
//------------------------------------

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdCookieManager, IdBaseComponent, IdComponent, IdTCPConnection,
IdTCPClient, IdHTTP;

type
TForm1 = class(TForm)
IdHTTP1: TIdHTTP;
IdCookieManager1: TIdCookieManager;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
Params: TStringList;
HTML, loginurl, myuser: String;
count,i:integer;
_cookies, cookies:tstringlist;
ll:boolean;
name,value:String;

procedure setcookies;
var j:integer; s:string;
begin
count:=cookies.count;
s:='';
for j:=1 to count do
begin
IdCookieManager1.AddCookie(cookies[j-1],IdHTTP1.url.Host);
s:=s+'; '+cookies[j-1];
end;
if s<>'' then
begin
delete(s,1,2);
s:=s+';';
IdHTTP1.Request.CustomHeaders.Values['Cookie']:=s;
IdHTTP1.Request.RawHeaders.Values['Cookie']:=s;
//('Cookie'+IdHTTP1.Request.RawHeaders.NameValueSeparator+s);
end;{}
end;

procedure extractcookie(cookie:string; var name,value:string);
var i,k:integer;
begin
i:=pos('=',cookie);
k:=pos(';',cookie);
if k=0 then k:=length(cookie);
if i>0 then
begin
name:=copy(cookie,1,i-1);
value:=copy(cookie,i+1,k-i-1);
end else
begin
name:='';
value:='';
end;
end;

procedure savecookies;
var j:integer;
begin
count:=IdCookieManager1.CookieCollection.count;
for j:=1 to count do
begin
extractcookie(IdCookieManager1.CookieCollection.Items[j-1].CookieText,name,value);
cookies.Values[name]:=value;
end;
// IdCookieManager1.CookieCollection.Clear;
end;

procedure saveit(name:string);
begin
with tfilestream.create(name,fmcreate) do
try
write(pansichar(html)^,length(html));
finally
free;
end;
end;

begin
ll:=false;
loginurl:='http://feedmelinks.com/login';
Params := TStringList.Create;
try
cookies:=tstringlist.Create;
// cookies.Duplicates:=dupIgnore;
// cookies.Sorted:=true;

idhttp1.Host:='feedmelinks.com';
html:=idhttp1.Get('http://feedmelinks.com/');// first get; get first cookie(s)
savecookies;

setcookies;
html:=idhttp1.Get(loginUrl);// next get; this is clean: used for retrieving the viewstate
savecookies;

myuser:='crystyignat';
Params.Values['userId'] := myuser;
Params.Values['password'] := 'mypassword';
Params.Values['op'] := 'login';

IdHTTP1.HandleRedirects:=false;// now this made the buzz, because the cookies were not set when following the redirect
try
setcookies;
HTML := IdHTTP1.Post(loginurl, Params);// now do the log in

_Cookies := TStringList.Create;
IdHTTP1.Response.RawHeaders.Extract('Set-cookie', _Cookies);
for i := 0 to _Cookies.Count - 1 do
begin
// IdCookieManager1.AddCookie(_Cookies[i], IdHTTP1.URL.Host);
extractcookie(_Cookies[i],name,value);
cookies.Values[name]:=value;
end;
_cookies.free;
// savecookies;

if pos('<div class="welcome">Welcome, <b>'+myuser+'</b>',html)>0 then
begin
setCookies;
html:=idhttp1.Get('http://feedmelinks.com/'); // software redirect
savecookies;

saveit('hhh.html');

// setCookies;
// html:=idhttp1.Get('http://feedmelinks.com/portal'); // another software redirect
//savecookies;

ll:=pos('<a class="tn" href="logout">log out',html)>0;
end;
except on e: EIdHTTPProtocolException do
begin
if e.ReplyErrorCode<>302 then
raise e;
// now this is the redirect
count:=IdCookieManager1.CookieCollection.count;// get the next cookie (this will be the userid)
for i:=1 to count do
cookies.Add(IdCookieManager1.CookieCollection.Items[i-1].CookieText);

setcookies;
html:=idhttp1.Get(IdHTTP1.Response.Location);// follow redirect
end;
end;

cookies.free;
except on e: EIdHTTPProtocolException do
begin
showmessage(idHTTP1.response.ResponseText);
end;
end;
Params.Free;
showmessage('logged in? : '+booltostr(ll,true));
end;

end.

 

=============================================================================================

 

IdHTTP造成程序假死的解决办法

 

在程序中使用了IdHTTP的话,在执行Get或Post过程的时候,程序界面会无法响应,造成程序假死,但在任务管理器中又能看到程序正在运行。

这是因为Indy系统组件都使用了阻塞式Sock,阻塞式Sock的缺点就是使客户程序的用户界面“冻结”。当在程序的主线程中进行阻塞式Socket调用时,由于要等待Socket调用完成并返回,这段时间就不能处理用户界面消息,使得Update、Repaint以及其它消息得不到及时响应,从而导致用户界面被“冻结”,就是常说的“程序假死”。

解决办法有两种:

1.在程序中放一个IdAntiFreeze控件,个人使用中发现把IdAntiFreeze控件的OnlyWhenIdle置为False,效果会更好。

2.将IdHTTP放进线程,在线程中动态建立IdHTTP控件来使用。

第一种办法使用简单,但程序界面的响应还是会有些延迟感。

第二种办法使用后,程序的表现十分好,感觉不到延迟。不过因为涉及到线程的操作,使用起来比第一种办法要麻烦一点。

 

=============================================================================================

 

用idhttp提交cookie

 

以前不管是做什么软件,只要是关于网页post提交cookie的,我都是用TcpClient,为什么呢?
因为我一直找不到idhttp提交Cookie的方法,今天终于有了结果。

在Idhttp中,要想修改Cookie的代码,就要用到Request的RawHeaders中的Values值。
这个值怎么用呢?
Values接受一个string的值,该值指定了所访问的变量。
如HTTP头是这样定义的(其中一些):
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; 
Cookie: JSESSIONID=aoOYvjM-IKzh 
而Values的值就可以是Cookie,User-Agent,Accept-Encoding……等等。

所以,代码应该是这样:
try
idhttp1.Request.RawHeaders.Values['Cookie'] := '这里是cookie的值'; //
memo1.Lines.Add(idhttp1.Request.RawHeaders.Values['Cookie']);
idhttp1.Post('/webmail/login.jsp',data1,data2);
memo1.Lines.Add(idhttp1.Request.RawHeaders.Values['Cookie']);
idhttp1.Request.RawHeaders.Values['Cookie'] := 'asdfasdf';
memo1.Lines.Add(idhttp1.Request.RawHeaders.Text);
except
idhttp1.Get(idhttp1.Response.Location, data1);
end; 
初一看,这代码是没有什么问题的。但,memo1的第一次ADD并没有任何值,奇怪。
而第三次ADD就被改为了'asdfasdf',正是我们所希望的。
我正是卡在了这里。为什么第一次idhttp1.Request.RawHeaders.Values['Cookie'] := '这里是cookie的值'; 没有结果呢?

搞了很久。我才发现,在第一次传值的时候,RawHeaders跟本没有被初始化。而第三次经过Post以后,RawHeaders被初始化了,所以得到了我们所要的结果。
也就是说,在写漏洞上传程序这些的时候,如果先Post让RawHeaders初始化,那就没什么意义了,因为Post的时候,Cookie就不能被带上了。

正确的代码应该是这样:
try
idhttp1.Request.SetHeaders; //最重要的初始化。
idhttp1.Request.RawHeaders.Values['Cookie'] := '这里是cookie的值';
idhttp1.Post('/webmail/login.jsp',data1,data2);
except
idhttp1.Get(idhttp1.Response.Location, data1);
end; 


这里,最重要的初始化是必需的。
idhttp1.Request.SetHeaders
这个过程如果没有。就会出错。

 

=============================================================================================

 

Delphi中使用IdHTTP来访问基于SSL协议的网站

 

今天有人问我使用idhttp如何去访问ssl协议的网站

很简单

在界面上放一个TIdHTTP控件,命名为IdHTTP1

再放一个TIdSSLIOHandlerSocket控件,命名为IdSSLIOHandlerSocket1

将IdHTTP1的IOHandler属性设为IdSSLIOHandlerSocket1

这样就可以随意的Get,Post那些地址为https开头的网站了

不过这样仍然不行,当运行程序时,会报错“Could not load SSL library”

这是因为TIdSSLIOHandlerSocket控件需要OpenSSL Library来配合

OpenSSL Library包含有两个动态链接库libeay32.dll和ssleay32.dll

据说因为OpenSSL Library中包含有安全方面的一些加密算法,所以美国政府把它列为禁止出口的产品,所以indy中并没有带上这两个文件

到网上搜索一下,很多地方都有下载,下回来放在程序目录里,就可以正常的使用IdHTTP来访问基于SSL协议的网站了

下面是网上找到的相关资料:

SSL (Secure Socket Layer)
为Netscape所研发,用以保障在Internet上数据传输之安全,利用数据加密(Encryption)技术,可确保数据在网络
上之传输过程中不会被截取及窃听。目前一般通用之规格为40 bit之安全标准,美国则已推出128 bit之更高安全
标准,但限制出境。只要3.0版本以上之I.E.或Netscape浏览器即可支持SSL。 
当前版本为3.0。它已被广泛地用于Web浏览器与服务器之间的身份认证和加密数据传输。
SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持。SSL协议可分为两层: SSL记录协议(SSL Record Protocol):它建立在可靠的传输协议(如TCP)之上,为高层协议提供数据封装、压缩、加密等基本功能的支持。 SSL握手协议(SSL Handshake Protocol):它建立在SSL记录协议之上,用于在实际的数据传输开始前,通讯双方进行身份认证、协商加密算法、交换加密密钥等。

SSL协议提供的服务主要有:
1)认证用户和服务器,确保数据发送到正确的客户机和服务器;
2)加密数据以防止数据中途被窃取;
3)维护数据的完整性,确保数据在传输过程中不被改变。

SSL协议的工作流程:
服务器认证阶段:1)客户端向服务器发送一个开始信息“Hello”以便开始一个新的会话连接;2)服务器根据客户的信息确定是否需要生成新的主密钥,如需要则服务器在响应客户的“Hello”信息时将包含生成主密钥所需的信息;3)客户根据收到的服务器响应信息,产生一个主密钥,并用服务器的公开密钥加密后传给服务器;4)服务器恢复该主密钥,并返回给客户一个用主密钥认证的信息,以此让客户认证服务器。
用户认证阶段:在此之前,服务器已经通过了客户认证,这一阶段主要完成对客户的认证。经认证的服务器发送一个提问给客户,客户则返回(数字)签名后的提问和其公开密钥,从而向服务器提供认证。
从SSL 协议所提供的服务及其工作流程可以看出,SSL协议运行的基础是商家对消费者信息保密的承诺,这就有利于商家而不利于消费者。在电子商务初级阶段,由于运作电子商务的企业大多是信誉较高的大公司,因此这问题还没有充分暴露出来。但随着电子商务的发展,各中小型公司也参与进来,这样在电子支付过程中的单一认证问题就越来越突出。虽然在SSL3.0中通过数字签名和数字证书可实现浏览器和Web服务器双方的身份验证,但是SSL协议仍存在一些问题,比如,只能提供交易中客户与服务器间的双方认证,在涉及多方的电子交易中,SSL协议并不能协调各方间的安全传输和信任关系。在这种情况下,Visa和 MasterCard两大信用卡公组织制定了SET协议,为网上信用卡支付提供了全球性的标准。


https介绍
HTTPS(Secure Hypertext Transfer Protocol)安全超文本传输协议 
它是由Netscape开发并内置于其浏览器中,用于对数据进行压缩和解压操作,并返回网络上传送回的结果。HTTPS实际上应用了Netscape的完全套接字层(SSL)作为HTTP应用层的子层。(HTTPS使用端口443,而不是象HTTP那样使用端口80来和TCP/IP进行通信。)SSL使用40 位关键字作为RC4流加密算法,这对于商业信息的加密是合适的。HTTPS和SSL支持使用X.509数字认证,如果需要的话用户可以确认发送者是谁。。
https是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,https的安全基础是SSL,因此加密的详细内容请看SSL。
它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。这个系统的最初研发由网景公司进行,提供了身份验证与加密通讯方法,现在它被广泛用于万维网上安全敏感的通讯,例如交易支付方面。
限制
它的安全保护依赖浏览器的正确实现以及服务器软件、实际加密算法的支持.
一种常见的误解是“银行用户在线使用https:就能充分彻底保障他们的银行卡号不被偷窃。”实际上,与服务器的加密连接中能保护银行卡号的部分,只有用户到服务器之间的连接及服务器自身。并不能绝对确保服务器自己是安全的,这点甚至已被攻击者利用,常见例子是模仿银行域名的钓鱼攻击。少数罕见攻击在网站传输客户数据时发生,攻击者尝试窃听数据于传输中。
商业网站被人们期望迅速尽早引入新的特殊处理程序到金融网关,仅保留传输码(transaction number)。不过他们常常存储银行卡号在同一个数据库里。那些数据库和服务器少数情况有可能被未授权用户攻击和损害。

 

=============================================================================================

 

Delphi编程中Http协议应用 -- idhttp

 

Delphi编程中Http协议应用 

来源:大富翁

 

Http协议的通信遵循一定的约定.例如,请求一个文件的时候先发送Get请求,然后服务器会返回请求的数据.如果需要进行断点传输,那么先发送HEAD /请求,其中返回的Content-Length: 就是文件实际大小.将其和我们本地需要断点下载的文件大小比较,发送GET请求和发送需要下载的文件开始位置RANGE: bytes=+inttostr(iFilePos)+-+#13#10;服务器如果支持断点下载的话就会接着发送余下的数据了.因为这方面的文章比较多,我在这里就不详细讲述了.感兴趣的朋友可以自行查阅相关资料或者RFC文档。

当然,如果你是个懒人,也可以直接采用Delphi自带的控件.以Delphi6的INDY组件为例.新建一个工程,放上一个TIdHTTP控件,一个TIdAntiFreeze控件,一个TProgressBar用于显示下载进度.最后放上一个TButton用于开始执行我们的命令.代码如下:

procedure TForm1.Button1Click(Sender: TObject);//点击按钮的时候开始下载我们的文件
var
MyStream:TMemoryStream;
begin
IdAntiFreeze1.OnlyWhenIdle:=False;//设置使程序有反应.
MyStream:=TMemoryStream.Create;
try
IdHTTP1.Gethttp://www.138soft.com/download/Mp3ToExe.zip,MyStream);//下载我站点的一个ZIP文件
except//INDY控件一般要使用这种try..except结构.
Showmessage(网络出错!);
MyStream.Free;
Exit;
end;
MyStream.SaveToFile(c:/Mp3ToExe.zip);
MyStream.Free;
Showmessage(OK);
end;

procedure TForm1.IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
const AWorkCountMax: Integer);//开始下载前,将ProgressBar1的最大值设置为需要接收的数据大小.
begin
ProgressBar1.Max:=AWorkCountMax;
ProgressBar1.Min:=0;
ProgressBar1.Position:=0;
end;

procedure TForm1.IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode;
const AWorkCount: Integer);//接收数据的时候,进度将在ProgressBar1显示出来.
begin
ProgressBar1.Position:=ProgressBar1.Position+AWorkCount;
end;

IdHTTP1的Get还有一种形式就是获取字符串:例如,上面的程序可以改写成:

procedure TForm1.Button1Click(Sender: TObject);
var
MyStr:String;
begin
IdAntiFreeze1.OnlyWhenIdle:=False;//设置使程序有反应.
try
MyStr:=IdHTTP1.Gethttp://www.138soft.com/default.htm);
except
Showmessage(网络出错!);
Exit;
end;
Showmessage(MyStr);
end;

应用:现在很多程序都有自动升级功能,实际上就是应用了GET.先在自己站点放一个文本文件注明程序版本号,当检查升级的时候,取文本内容与当前版本号比较,然后决定升级与否.

 

转的目的是为了试试进度条的效果.

 

=============================================================================================

 

IDHttp的基本用法

 

IDHttp和WebBrowser一样,都可以实现抓取远端网页的功能,但是http方式更快、更节约资源,缺点是需要手动维护cook,连接等

IDHttp的创建,需要引入IDHttp

procedure InitHttp();
begin
    http := TIdHTTP.Create(nil);
    http.ReadTimeout := 30000;
    http.OnRedirect := OnRedirect;
    http.Request.Accept := 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, */*';
    http.Request.AcceptLanguage := 'zh-cn';
    http.Request.ContentType := 'application/x-www-form-urlencoded';
    http.Request.UserAgent := 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322)';

    http.ProxyParams.ProxyServer := '代理服务器地址';
    http.ProxyParams.ProxyPort := '代理服务器端口';
end;

如何取得服务端返回的cookie信息,并添加到http的request对象中

procedure Setcookie;
var
i: Integer;
tmp, cookie: String;
begin
cookie := '';
for i := 0 to http.Response.RawHeaders.Count - 1 do
begin
    tmp := http.Response.RawHeaders[i];
    if pos('set-cookie: ', LowerCase(tmp)) = 0 then Continue;
    tmp := Trim(Copy(tmp, Pos('Set-cookie: ', tmp) + Length('Set-cookie: '), Length(tmp)));
    tmp := Trim(Copy(tmp, 0, Pos(';', tmp) - 1));
    if cookie = '' then cookie := tmp else cookie := cookie + '; ' + tmp;
end;
if cookie <> '' then
begin
    for i := 0 to http.Request.RawHeaders.Count - 1 do
    begin
      tmp := http.Request.RawHeaders[i];
      if Pos('cookie', LowerCase(tmp)) = 0 then Continue;
      http.Request.RawHeaders.Delete(i);
      Break;
    end;
    http.Request.RawHeaders.Add('cookie: ' + cookie);
end;
end;

如何取得网页中的所有连接,对代码做修改你也可以实现查找所有图片等等, QStrings.rar(79K) (点击下载)在这里推荐使用QString来实现文本替换、查找等功能,附件里有下载。

function GetURLList(Data: String): TStringList;
var
i: Integer;
List: TStringList;
tmp: String;

function Split(Data, Node: String): TStringList;
var
   Count, i, j: Integer;
    function GetFieldCount(Data, Node: String): Integer;
    var
     i: Integer;
   begin
    Result := -1;
     i := Pos(Node, Data);
      if i = 0 then Exit;
     Result := 0;
    while i <> 0 do
     begin
      Inc(Result);
       Delete(Data, 1, i + Length(Node) - 1);
      i := Pos(Node, Data);
    end;
   end;
begin
Result := TStringList.Create;
Count := GetFieldCount(Data, Node);
for i := 0 to Count - 1 do
begin
    j := Pos(Node, Data);
    Result.Add(Copy(Data, 1, j - 1));
    Delete(Data, 1, j + Length(Node) - 1);
end;
Result.Add(Data);
end;
begin
Result := TStringList.Create;
try
    List := split(Data, 'href=');
    for i := 1 to List.Count - 1 do
    begin
      tmp := List[i];
      tmp := Copy(tmp, 0, Pos('</a>', tmp) - 1);
      tmp := Copy(tmp, 0, Pos('>', tmp) - 1);
      if Pos(' ', tmp) <> 0 then tmp := Copy(tmp, 0, Pos(' ', tmp) - 1);
      tmp := Q_ReplaceStr(tmp, Char(34), '');
      tmp := Q_ReplaceStr(tmp, Char(39), '');
      if not Compare(CI.Key, tmp) then Continue;
      if Copy(tmp, 1, 7) <> 'http://' then
      begin
        if Copy(tmp, 1, 1) = '.' then tmp := StringReplace(tmp, '.', '', []);
        if Copy(tmp, 1, 1) = '.' then tmp := StringReplace(tmp, '.', '', []);
        try
          tmp := 'http://' + http.URL.Host + ':' + http.URL.Port + http.URL.Path + tmp;
        except
        end;
      end;
      if Result.IndexOf(tmp) <> -1 then Continue;
      Result.Add(tmp);
    end;
    FreeAndNil(List);
except

end;
end;

如何模拟http的get方法打开一个网页

function GetMethod(http: TIDhttp; URL: String; Max: Integer): String;
var
RespData: TStringStream;
begin
RespData := TStringStream.Create('');
try
    try
      Http.Get(URL, RespData);
      Http.Request.Referer := URL;
      Result := RespData.DataString;
    except
      Dec(Max);
      if Max = 0 then
      begin
        Result := '';
        Exit;
      end;
      Result := GetMethod(http, URL, Max);
    end;
finally
    FreeAndNil(RespData);
end;
end;

如何模拟http的post方法提交一个网页

function PostMethod(URL, Data: String; max: Integer): String;
var
PostData, RespData: TStringStream;
begin
RespData := TStringStream.Create('');
PostData := TStringStream.Create(Data);
try
    try
      if http = nil then Exit;
      Http.Post(URL, PostData, RespData);
      Result := RespData.DataString;
      http.Request.Referer := URL;
    except
      Dec(Max);
      if Max = 0 then
      begin
        Result := '';
        Exit;
      end;
      Result := PostMethod(URL, Data, Max);
    end;
finally
    http.Disconnect;
    FreeAndNil(RespData);
    FreeAndNil(PostData);
end;
end;

程序写好了,如何调试?这里推荐一个小工具 httplook.part1.rar(782K) (点击下载)httplook.part2.rar(243K) (点击下载),可以监视你的流程是否正确

总结:IDHttp的基本用法已经讲解完毕,其实通过IDHttp返回的就是2个东西,网页的header和网页的body,网页的header中包含了cookie、跳转等信息,body中就包含了内容,我们写程序就是通过查找、拷贝、替换等方式把其中的关键数据找出来,然后做处理,说简单了就是考验你的字符串操作能力。

 

=============================================================================================

 

IdHTTP多线程下载

 

IdHTTP多线程下载
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls, IdComponent, IdTCPConnection, IdTCPClient,
IdHTTP, IdBaseComponent, IdAntiFreezeBase, IdAntiFreeze,
IdThreadComponent, IdFTP;

type
TThread1 = class(TThread)

private
    fCount, tstart, tlast: integer;
    tURL, tFile, temFileName: string;
    tResume: Boolean;
    tStream: TFileStream;
protected
    procedure Execute; override;
public
    constructor create1(aURL, aFile, fileName: string; bResume: Boolean; Count,
      start, last: integer);
    procedure DownLodeFile(); //下载文件
end;

type
TForm1 = class(TForm)
    IdAntiFreeze1: TIdAntiFreeze;
    IdHTTP1: TIdHTTP;
    Button1: TButton;
    ProgressBar1: TProgressBar;
    IdThreadComponent1: TIdThreadComponent;
    Label1: TLabel;
    Label2: TLabel;
    Button2: TButton;
    Button3: TButton;
    ListBox1: TListBox;
    Edit1: TEdit;
    Edit2: TEdit;
    Label3: TLabel;
    Label4: TLabel;

    procedure Button1Click(Sender: TObject);
    procedure IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
      const AWorkCountMax: Integer);
    procedure IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode;
      const AWorkCount: Integer);
    procedure Button2Click(Sender: TObject);
    procedure IdHTTP1Status(ASender: TObject; const AStatus: TIdStatus;
      const AStatusText: string);
    procedure Button3Click(Sender: TObject);
private
public
    nn, aFileSize, avg: integer;
    MyThread: array[1..10] of TThread;
    procedure GetThread();
    procedure AddFile();
    function GetURLFileName(aURL: string): string;
    function GetFileSize(aURL: string): integer;
end;

var
Form1: TForm1;

implementation
var
AbortTransfer: Boolean;
aURL, aFile: string;

tcount: integer; //检查文件是否全部下载完毕
{$R *.dfm}

//get FileName

function TForm1.GetURLFileName(aURL: string): string;
var
i: integer;
s: string;
begin //返回下载地址的文件名

s := aURL;
i := Pos('/', s);
while i <> 0 do //去掉"/"前面的内容剩下的就是文件名了
begin
    Delete(s, 1, i);
    i := Pos('/', s);
end;
Result := s;
end;

//get FileSize

function TForm1.GetFileSize(aURL: string): integer;
var
FileSize: integer;
begin
IdHTTP1.Head(aURL);
FileSize := IdHTTP1.Response.ContentLength;
IdHTTP1.Disconnect;
Result := FileSize;
end;

//执行下载

procedure TForm1.Button1Click(Sender: TObject);
var
j: integer;
begin
tcount := 0;
Showmessage('OK!主线程在执行,获得文件名并显示在Edit2中');
aURL := Edit1.Text; //下载地址
aFile := GetURLFileName(Edit1.Text); //得到文件名
nn := StrToInt(Edit2.Text); //线程数
j := 1;
aFileSize := GetFileSize(aURL);
avg := trunc(aFileSize / nn);
begin
    try
      GetThread();
      while j <= nn do
      begin
        MyThread[j].Resume; //唤醒线程
        j := j + 1;
      end;
    except
      Showmessage('创建线程失败!');
      Exit;
    end;
end;
end;

//开始下载前,将ProgressBar1的最大值设置为需要接收的数据大小.

procedure TForm1.IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
const AWorkCountMax: Integer);
begin
AbortTransfer := False;
ProgressBar1.Max := AWorkCountMax;
ProgressBar1.Min := 0;
ProgressBar1. 0;
end;

//接收数据的时候,进度将在ProgressBar1显示出来.

procedure TForm1.IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode;
const AWorkCount: Integer);
begin
if AbortTransfer then
begin
    IdHTTP1.Disconnect; //中断下载
end;
ProgressBar1. AWorkCount;
//ProgressBar1.; //*******显示速度极快
Application.ProcessMessages;
//***********************************这样使用不知道对不对

end;

//中断下载

procedure TForm1.Button2Click(Sender: TObject);
begin
AbortTransfer := True;
IdHTTP1.Disconnect;
end;

//状态显示

procedure TForm1.IdHTTP1Status(ASender: TObject; const AStatus: TIdStatus;
const AStatusText: string);
begin
ListBox1.ItemIndex := ListBox1.Items.Add(AStatusText);
end;

//退出程序

procedure TForm1.Button3Click(Sender: TObject);
begin
application.Terminate;

end;

//循环产生线程

procedure TForm1.GetThread();
var
i: integer;
start: array[1..100] of integer;
last: array[1..100] of integer;   //改用了数组,也可不用
fileName: string;
begin
i := 1;
while i <= nn do
begin
    start[i] := avg * (i - 1);
    last[i] := avg * i -1; //这里原先是last:=avg*i;
    if i = nn then
    begin
      last[i] := avg*i + aFileSize-avg*nn; //这里原先是aFileSize
    end;
    fileName := aFile + IntToStr(i);
    MyThread[i] := TThread1.create1(aURL, aFile, fileName, false, i, start[i],
      last[i]);
    i := i + 1;
end;
end;

procedure TForm1.AddFile(); //合并文件
var
mStream1, mStream2: TMemoryStream;
i: integer;
begin
i := 1;
mStream1 := TMemoryStream.Create;
mStream2 := TMemoryStream.Create;

mStream1.loadfromfile('设备工程进度管理前期规划.doc' + '1');
while i < nn do
begin
    mStream2.loadfromfile('设备工程进度管理前期规划.doc' + IntToStr(i + 1));
    mStream1.seek(mStream1.size, soFromBeginning);
    mStream1.copyfrom(mStream2, mStream2.size);
    mStream2.clear;
    i := i + 1;
end;
mStream2.free;
mStream1.SaveToFile('设备工程进度管理前期规划.doc');
mStream1.free;
//删除临时文件
i:=1;
   while i <= nn do
begin
    deletefile('设备工程进度管理前期规划.doc' + IntToStr(i));
    i := i + 1;
end;
Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('下在成功');

end;

//构造函数

constructor TThread1.create1(aURL, aFile, fileName: string; bResume: Boolean;
Count, start, last: integer);
begin
inherited create(true);
FreeOnTerminate := true;
tURL := aURL;
tFile := aFile;
fCount := Count;
tResume := bResume;
tstart := start;
tlast := last;
temFileName := fileName;
end;
//下载文件函数

procedure TThread1.DownLodeFile();
var
temhttp: TIdHTTP;
begin

temhttp := TIdHTTP.Create(nil);
temhttp.onWorkBegin := Form1.IdHTTP1WorkBegin;
temhttp.onwork := Form1.IdHTTP1work;
temhttp.onStatus := Form1.IdHTTP1Status;
Form1.IdAntiFreeze1.OnlyWhenIdle := False; //设置使程序有反应.
if FileExists(temFileName) then //如果文件已经存在
    tStream := TFileStream.Create(temFileName, fmOpenWrite)
else
    tStream := TFileStream.Create(temFileName, fmCreate);

if tResume then //续传方式
begin
    exit;
end
else //覆盖或新建方式
begin
    temhttp.Request.ContentRangeStart := tstart;
    temhttp.Request.ContentRangeEnd := tlast;
end;

try
    temhttp.Get(tURL, tStream); //开始下载
    Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add(temFileName +
      'download');

finally
    //tStream.Free;
    freeandnil(tstream);
    temhttp.Disconnect;
end;

end;

procedure TThread1.Execute;
begin
if Form1.Edit1.Text <> '' then
    //synchronize(DownLodeFile)
    DownLodeFile
else
    exit;
inc(tcount);
if tcount = Form1.nn then //当tcount=nn时代表全部下载成功
begin
    //Showmessage('全部下载成功!');
    Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('正在合并删除临时文件');
    Form1.AddFile;
end;
end;

end.

 

=============================================================================================

 

在idhttp中如何实现多线程

 

unit1:
       unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, DB, ADODB, IdAntiFreezeBase, IdAntiFreeze,
  IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Label1: TLabel;
    Button1: TButton;
    Memo1: TMemo;
    ADOQuery1: TADOQuery;
    ADOConnection1: TADOConnection;
    IdHTTP1: TIdHTTP;
    IdAntiFreeze1: TIdAntiFreeze;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  Count : Integer;
  procedure ThreadDone(Sender: TObject);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation
uses Unit2;

var
  gt : array[1..4] of gethtml;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  i : Integer;
  str_url : string;
begin
  Count := 0;
  str_url := 'http://www.newjobs.com.cn/qiuzhiguwen/job.jsp?num=60347';
  for i := 1 to 4 do
  begin
      gt[i]:=gethtml.Create(str_url);
      gt[i].OnTerminate := ThreadDone;
  end;
end;

procedure TForm1.ThreadDone(Sender: TObject);
begin
  Inc(Count);
  Memo1.Lines.Add('当前完成线程数:'+IntToStr(Count));
end;

end.

--------------------------------------------------------------------------------------------------------------------------
============================================================================
unit2:
unit Unit2;

interface

uses
  IdHTTP, IdTCPConnection, IdTCPClient, Classes, Dialogs, Graphics, Controls,
  SysUtils, Windows, Messages, Variants, StdCtrls;

type
  gethtml = class(TThread)
  private
    { Private declarations }
    furl:string;
  protected
    procedure Execute; override;
  public
    constructor Create(url:string);
  end;

implementation

uses Unit1;

constructor gethtml.Create(url:string);
begin
  inherited Create(FALSE);
  furl:= url;
end;

procedure gethtml.Execute;
var
  st: TStringStream;
  IdHTTP: TIdHTTP;
begin
  st := TStringStream.Create('');
  ReturnValue := 10000;
  IdHTTP := TIdHTTP.Create(nil);
  IdHTTP.HandleRedirects := True;
  IdHTTP.ReadTimeout := 60000;
  try
    IdHTTP.Get(furl,st);
    Form1.Memo1.Text := st.DataString;//这里操作方法有错误,么有同步,多线程等着出错吧
    //FiState^ := True;
  except
    //FiState^ := False;
  end;  
  IdHTTP.Free;
  st.Free;
  inherited;
end;

end.

 

=============================================================================================

 

相对完整的多线程idhttp文件下载代码

 

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls, IdComponent, IdTCPConnection, IdTCPClient,
  IdHTTP, IdBaseComponent, IdAntiFreezeBase, IdAntiFreeze,
  IdThreadComponent, IdFTP ,IdException;
type
  MyException1 = class(exception)//自定义的异常类
end;

type
  TThread1 = class(TThread)

  private
    fCount, tstart, tlast: integer;
    tURL, tFile, temFileName: string;
    tResume: Boolean;
    tStream: TFileStream;
  protected
    procedure Execute; override;
  public
    constructor create1(aURL, aFile, fileName: string; bResume: Boolean; Count,
      start, last: integer);
    procedure DownLodeFile(); //下载文件
  end;


type
  TForm1 = class(TForm)
    IdAntiFreeze1: TIdAntiFreeze;
    IdHTTP1: TIdHTTP;
    Button1: TButton;
    ProgressBar1: TProgressBar;
    Label1: TLabel;
    Label2: TLabel;
    Button2: TButton;
    Button3: TButton;
    ListBox1: TListBox;
    Edit1: TEdit;
    Edit2: TEdit;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    SaveDialog1: TSaveDialog;

    procedure Button1Click(Sender: TObject);
    procedure IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
      const AWorkCountMax: Integer);
    procedure IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode;
      const AWorkCount: Integer);
    procedure Button2Click(Sender: TObject);
    procedure IdHTTP1Status(ASender: TObject; const AStatus: TIdStatus;
      const AStatusText: string);
    procedure Button3Click(Sender: TObject);
  private
  public
    nn, aFileSize, avg: integer;
    time1, time2: TDateTime;
    MyThread: array[1..10] of TThread;
    procedure GetThread();
    procedure AddFile();
    procedure NewAddFile();
    function GetURLFileName(aURL: string): string;
    function GetFileSize(aURL: string): integer;
  end;

var
  Form1: TForm1;

implementation
var
  AbortTransfer: Boolean;
  aURL, aFile: string;
  tcount: integer; //检查文件是否全部下载完毕
{$R *.dfm}

  //get FileName

function TForm1.GetURLFileName(aURL: string): string;
var
  i: integer;
  s: string;
begin //返回下载地址的文件名

  s := aURL;
  i := Pos('/', s);
  while i <> 0 do //去掉"/"前面的内容剩下的就是文件名了
  begin
    Delete(s, 1, i);
    i := Pos('/', s);
  end;
  Result := s;
end;

//get FileSize

function TForm1.GetFileSize(aURL: string): integer;
var
  FileSize: integer;
begin
  IdHTTP1.Head(aURL);
  FileSize := IdHTTP1.Response.ContentLength;
  IdHTTP1.Disconnect;
  Result := FileSize;
end;

//执行下载

procedure TForm1.Button1Click(Sender: TObject);
var
  j: integer;
begin
    //savedialog1.
  try
    time1 := Now;
    tcount := 0;
    aURL := Edit1.Text; //下载地址
    if aURL = '' then
    begin
       MessageDlg('请输入下载地址!',mtError,[mbOK],0);
       Exit;
    end;
    aFile := GetURLFileName(Edit1.Text); //得到文件名
    savedialog1.FileName :=afile;
    if savedialog1.Execute then


    if Edit2.Text = '' then
    begin
      case MessageDlg('请输入线程数,最大支持10个线程,默认为单线程下载!', mtConfirmation, [mbYes, mbNo], 0) of
        mrYes: nn:=1; //默认
        mrNo: Exit; //重新输入
      end;
    end
    else
      nn := StrToInt(Edit2.Text); //线程数
      if nn > 10 then
      begin
        raise MyException1.Create('输入超过线程限制数,请重新输入!');
      end;
      j := 1;
      aFileSize := GetFileSize(aURL);
      avg := trunc(aFileSize / nn);
      begin
        try
          GetThread();
          while j <= nn do
          begin
            MyThread[j].Resume; //唤醒线程
            j := j + 1;
          end;
        except
          Showmessage('创建线程失败!');
          Exit;
        end;
      end;
  except
    on E:EConvertError do//捕捉内建的Econverterror异常
    begin
      //ShowMessage('请输入数字');
      MessageDlg('请输入数字'+#13,mtError,[mbOK],0);
      Exit;
    end;
    on E:MyException1 do//捕捉自定义的MyException异常
    begin
      MessageDlg(E.Message,mtError,[mbOK],0);
      Edit2.Text:= '';
      Exit;
    end;
    on E:EIdSocketError do//捕捉内建的EIdSocketError异常
    begin
      MessageDlg('连接不上服务器,或服务起未开启!',mtError,[mbOK],0);
      Exit;
    end;
    on E:EIdConnectException do//捕捉内建的EIdSocketError异常
    begin
      MessageDlg('连接不上服务器,或服务起未开启!',mtError,[mbOK],0);
      Exit;
    end;
    on E:EIdHTTPProtocolException do//捕捉内建的EIdSocketError异常
    begin
      MessageDlg('目标文件找不到!',mtError,[mbOK],0);
      Exit;
    end;
  else
    raise //reraise其他异常

  end;
end;

//开始下载前,将ProgressBar1的最大值设置为需要接收的数据大小.

procedure TForm1.IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
  const AWorkCountMax: Integer);
begin
  AbortTransfer := true;
  ProgressBar1.Max := AWorkCountMax;
  ProgressBar1.Min := 0;
  ProgressBar1.Position := 0;
end;

//接收数据的时候,进度将在ProgressBar1显示出来.

procedure TForm1.IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode;
  const AWorkCount: Integer);
begin
  if AbortTransfer then
  begin
    //IdHTTP1.Disconnect; //中断下载
  end;

  ProgressBar1.Position := AWorkCount;
  //ProgressBar1.Position:=ProgressBar1.Position+AWorkCount; //*******显示速度极快
  Application.ProcessMessages;
  //***********************************这样使用不知道对不对

end;

//中断下载

procedure TForm1.Button2Click(Sender: TObject);
var
  i : integer;
begin
  try
    if AbortTransfer then
      begin
        i:=1;
        while i <= nn do
          begin
          MyThread[i].Suspend;
          i := i + 1;
           end;
       AbortTransfer := false;
       button2.Caption:='开始';
   end else
     begin
     i:=1;
     while i <= nn do
       begin
       MyThread[i].Resume;
       i := i + 1;
       end;
      AbortTransfer := True;
     button2.Caption:='暂停';
    end;
  except
    on E:EThread do
    begin
    end;
  else
    raise //reraise其他异常
end;
  //IdHTTP1.Disconnect;
end;

//状态显示

procedure TForm1.IdHTTP1Status(ASender: TObject; const AStatus: TIdStatus;
  const AStatusText: string);
begin
  ListBox1.ItemIndex := ListBox1.Items.Add(AStatusText);
end;

//退出程序

procedure TForm1.Button3Click(Sender: TObject);
begin
  //application.Terminate;
  IdHTTP1.DisconnectSocket;
  Form1.close;

end;

//循环产生线程

procedure TForm1.GetThread();
var
  i: integer;
  start: array[1..100] of integer;
  last: array[1..100] of integer;   //改用了数组,也可不用
  fileName: string;
begin
  i := 1;
  while i <= nn do
  begin
    start[i] := avg * (i - 1);
    last[i] := avg * i -1; //这里原先是last:=avg*i;
    if i = nn then
    begin
      last[i] := avg*i + aFileSize-avg*nn; //这里原先是aFileSize
    end;
    fileName := aFile + IntToStr(i);
    MyThread[i] := TThread1.create1(aURL, aFile, fileName, false, i, start[i],
      last[i]);
    i := i + 1;
  end;
end;

procedure TForm1.AddFile(); //合并文件
var
  mStream1, mStream2: TMemoryStream;
  i: integer;
begin
try
  i := 1;
  mStream1 := TMemoryStream.Create;
  mStream2 := TMemoryStream.Create;

  mStream1.loadfromfile(afile + '1');
  while i < nn do
  begin
    mStream2.loadfromfile(afile + IntToStr(i + 1));
    mStream1.seek(mStream1.size, soFromBeginning);
    mStream1.copyfrom(mStream2, mStream2.size);
    mStream2.clear;
    i := i + 1;
  end;
  FreeAndNil(mStream2);
  mStream1.SaveToFile(afile);
  FreeAndNil(mStream1);
  //删除临时文件
  i:=1;
   while i <= nn do
  begin
    deletefile(afile + IntToStr(i));
    i := i + 1;
  end;
  Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('下载成功');
except
    i:=1;
    while i <= nn do
    begin
    if FileExists(aFile+inttostr(i)) then
    deletefile(afile + IntToStr(i));
    i := i + 1;
    end;
    ShowMessage('下载文件出错,临时文件已删除,请重新下载!')
  end;

end;

procedure TForm1.NewAddFile(); //合并文件
var
  i: Integer;
  InStream, OutStream : TFileStream;
  SourceFile : String;
begin
  try
    i := 1;
    OutStream:=TFileStream.Create(aFile,fmCreate);
    //OutStream:=TFileStream.Create(('D/1/'+aFile),fmCreate); //此句与savedialog冲突,发生异常,使savedialog指定路径无效。
    while i <= nn do
    begin
      SourceFile := afile + IntToStr(i);
      InStream:=TFileStream.Create(SourceFile, fmOpenRead);
      OutStream.CopyFrom(InStream,0);
      FreeAndNil(InStream);
      i:= i+1;
    end;
    FreeAndNil(OutStream);
    //删除临时文件
    i:=1;
    while i <= nn do
    begin
    deletefile(afile + IntToStr(i));
    i := i + 1;
    end;

  except
    i:=1;
    while i <= nn do
    begin
    if FileExists(aFile+inttostr(i)) then
    deletefile(afile + IntToStr(i));
    i := i + 1;
    end;
  end;
  if FileExists(aFile) then
  begin
    FreeAndNil(OutStream);
    InStream := TFileStream.Create(aFile, fmOpenWrite);
    if InStream.Size < aFileSize then
    begin
      FreeAndNil(InStream);
      deletefile(afile);
      //ShowMessage('下载文件出错,临时文件已删除,请重新下载!')
      Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('下载文件出错,临时文件已删除,请重新下载!');
    end
    else
    begin
      FreeAndNil(InStream);
      Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('下在成功');
    end;
  end;

 
  
end;


//构造函数

constructor TThread1.create1(aURL, aFile, fileName: string; bResume: Boolean;
  Count, start, last: integer);
begin
  inherited create(true);
  FreeOnTerminate := true;
  tURL := aURL;
  tFile := aFile;
  fCount := Count;
  tResume := bResume;
  tstart := start;
  tlast := last;
  temFileName := fileName;
end;
//下载文件函数

procedure TThread1.DownLodeFile();
var
  temhttp: TIdHTTP;
begin

  temhttp := TIdHTTP.Create(nil);
  temhttp.onWorkBegin := Form1.IdHTTP1WorkBegin;
  temhttp.onwork := Form1.IdHTTP1work;
  temhttp.onStatus := Form1.IdHTTP1Status;
  Form1.IdAntiFreeze1.OnlyWhenIdle := False; //设置使程序有反应.
  if FileExists(temFileName) then //如果文件已经存在
    tStream := TFileStream.Create(temFileName, fmOpenWrite)
  else
    tStream := TFileStream.Create(temFileName, fmCreate);

  if tResume then //续传方式
  begin
    exit;
  end
  else //覆盖或新建方式
  begin
    temhttp.Request.ContentRangeStart := tstart;
    temhttp.Request.ContentRangeEnd := tlast;
  end;

  try
    ///try
      temhttp.Get(tURL, tStream); //开始下载
    except
      if FileExists(temFileName) then
      begin
      freeandnil(tstream);
      deletefile(temFileName);//本来想用来删除未下完的文件,可惜不成功,有的线程没有删除,只有部分删除了,
                              //不过这样导致后面合并文件时出错,同样也可以把临时文件删除。
      //ShowMessage('下载文件出错,临时文件已删除,请重新下载!');/
      end;
      temhttp.Disconnect;
    end;

    Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add(temFileName +
      'download');

  //finally
    freeandnil(tstream);
    temhttp.Disconnect;
  //end;

end;

procedure TThread1.Execute;
begin

  if Form1.Edit1.Text <> '' then
    //synchronize(DownLodeFile)
    DownLodeFile
  else
    exit;
  inc(tcount);
  if tcount = Form1.nn then //当tcount=nn时代表全部下载成功
  begin
    Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('正在合并删除临时文件');
    Form1.NewAddFile;
    form1.time2 := Now;
    Form1.Label5.Caption := FormatDateTime ('n:ss', form1.Time2-Form1.Time1) + ' seconds';
  end;

end;

end. 

=============================================================================================

 

idhttp下载html的代码(含错误处理)

 

IdHTTP_Thread := TIDHTTP.Create;
     IdHTTP_Thread.ReadTimeout  := 240000;
     IdHTTP_Thread.ConnectTimeout := 240000;
     IdHTTP_Thread.Request.UserAgent :='Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)';
     try
       try
         TStmHtml := TStringStream.Create('');
         IdHTTP_Thread.Get(FGetURL,TStmHtml);
         strHtml := TStmHtml.DataString   ;
         //strHtml :=  FParameter;
       except
          on E:EIdSocketError  do
          begin
            FImpInfo := IntToStr(iLoop)+' 获得'+FGetURL+'职位信息时出现错误丢失一页 错误原因: '+SysErrorMessage(E.LastError );
            FErrCode := E.LastError;
            ReGetHtml := True;
          end;
          else
          begin
            FImpInfo := IntToStr(iLoop)+' 获得'+FGetURL+'职位信息时出现错误丢失一页 错误原因: 打开网页失败';
            FErrCode := 1 ;
            ReGetHtml := True;
          end;
       end;
     finally
        IdHTTP_Thread.Disconnect ;
        IdHTTP_Thread.Free  ;
        TStmHtml.Free  ;
     end;

=============================================================================================

 

用idhttp提交自己构造过的Cookie

 

如何用idhttp提交自己构造过的Cookie

我不知道的是:如果把自己构造过的Cookie传给idhttp让它提交。

比如站点 http://www.aaa.com 是要cookie的。
我已经在程序上放了idhttp和IdCookieManager。
我get http://www.aaa.com 后,idhttp通过IdCookieManager已经得到当前站点的Cookie了。
我可以用
for i := 0 to IdCookieManager1.CookieCollection.Count - 1 do
memo1.Lines.Add(IdCookieManager1.CookieCollection.Items[i].CookieText);
得到。

现在,如果我想更改这个cookie,或者说我想按这个Cookie的格式重新写一个,再用idhttp进行post。我应该怎么做?
用途是Cookie欺骗等。
如:
得到的Cookie为:skin=2; ASPSESSIONIDSQTSABQD=IEMKPIDBKKMEEKEHLLOIJJON; UserCode=3CA001D63984E6115FE55681%2E95
我更改为:skin=123; ASPSESSIONIDSQTSABQD=IEMKPIDBKKMEEKEHLLOIJJON; UserCode=3CA001D63984E6115FE55681%2E95
我再post  

今天忙了一个下午,终于研究出答案了。

以前不管是做什么软件,只要是关于网页post提交cookie的,我都是用TcpClient,为什么呢?
因为我一直找不到idhttp提交Cookie的方法,今天终于有了结果。

在Idhttp中,要想修改Cookie的代码,就要用到Request的RawHeaders中的Values值。
这个值怎么用呢?
Values接受一个string的值,该值指定了所访问的变量。
如HTTP头是这样定义的(其中一些):
[color=royalblue]Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; 
Cookie: JSESSIONID=aoOYvjM-IKzh[/color]
而Values的值就可以是Cookie,User-Agent,Accept-Encoding……等等。

所以,代码应该是这样:
[color=royalblue] try
idhttp1.Request.RawHeaders.Values['Cookie'] := '这里是cookie的值'; //
memo1.Lines.Add(idhttp1.Request.RawHeaders.Values['Cookie']);
idhttp1.Post('/webmail/login.jsp',data1,data2);
memo1.Lines.Add(idhttp1.Request.RawHeaders.Values['Cookie']);
idhttp1.Request.RawHeaders.Values['Cookie'] := 'asdfasdf';
memo1.Lines.Add(idhttp1.Request.RawHeaders.Text);
except
idhttp1.Get(idhttp1.Response.Location, data1);
end;[/color]
初一看,这代码是没有什么问题的。但,memo1的第一次ADD并没有任何值,奇怪。
而第三次ADD就被改为了'asdfasdf',正是我们所希望的。
我正是卡在了这里。为什么第一次idhttp1.Request.RawHeaders.Values['Cookie'] := '这里是cookie的值'; 没有结果呢?

搞了很久。我才发现,在第一次传值的时候,RawHeaders跟本没有被初始化。而第三次经过Post以后,RawHeaders被初始化了,所以得到了我们所要的结果。

正确的代码应该是这样:
[color=royalblue]try
idhttp1.Request.SetHeaders; //最重要的初始化。
idhttp1.Request.RawHeaders.Values['Cookie'] := '这里是cookie的值';
idhttp1.Post('/webmail/login.jsp',data1,data2);
except
idhttp1.Get(idhttp1.Response.Location, data1);
end;[/color]

 

=============================================================================================

 

Idhttp自动发贴 for Discuz

 

先是自动登录函数,登录后再GET一下取得发贴时要的formhash值,存入全局变量。

function TForm1.LoginOn(strUser, strPass: string): Boolean;
var
Param:TStringList;
url,HTML:String;
begin
Result:=False;
idhtp1.AllowCookies:=True;
idhtp1.HandleRedirects:=True;
idhtp1.Request.ContentType:='application/x-www-form-urlencoded' ;
idhtp1.Request.UserAgent:='Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 2.0.50727)';
Param:=TStringList.Create;
//Param.Add('formhash=6a68324b');
//Param.Add('cookietime=2592000');
Param.Add('loginfield=username');
Param.Add('username='+strUser);
Param.Add('password='+strPass);
Param.Add('userlogin=%E7%99%BB%E5%BD%95');
url:='http://localhost/bbs/logging.php?action=login&loginsubmit=true';
try
    HTML:=idhtp1.Post(Url,Param);
    HTML:=UTF8Decode(HTML);
finally
    Param.Free;
end;
Result:= (Pos('退出',HTML)>0);
HTML:=idhtp1.Get('http://localhost/bbs/index.php');
formhash:=Copy(HTML,Pos('formhash=',HTML)+9,100);
formhash:=Copy(formhash,1,Pos('"',formhash)-1);

end;

发一个新主题。fid为板块序号

function TForm1.NewSubject(fid,Subject, Content: string): String;
var
Param:TStringList;
url,HTML:String;
begin
Param:=TStringList.Create;
Param.Add('formhash='+formhash);
Param.Add('frombbs=1');
Param.Add('subject='+Subject);
Param.Add('message='+Content);
url:='http://localhost/bbs';
url:=url+'/post.php?action=newthread&fid=';
url:=url+fid;
url:=url+'&extra=page%3D1&topicsubmit=yes';
try
    HTML:=idhtp1.Post(Url,Param);
    HTML:=UTF8Decode(HTML);
finally
    Param.Free;
end;
result:=copy(HTML,Pos('tid=',HTML)+4,50);
result:=Copy(Result,1,Pos('&',result)-1);
end;

回复主题。tid为主题序号。

function TForm1.ReSubject(fid,tid,Subject, Content: string):String;
var
Param:TStringList;
url,HTML:string;
begin
Param:=TStringList.Create;
Param.Add('formhash='+formhash);
Param.Add('frombbs=1');
Param.Add('subject='+Subject);
Param.Add('message='+Content);
url:='http://localhost/bbs';
url:=url+'/post.php?action=reply&fid=';
url:=url+fid+'&tid='+tid;
url:=url+'&extra=page%3D1&replysubmit=yes';
try
    HTML:=idhtp1.Post(Url,Param);
    //HTML:=UTF8Decode(HTML);
finally
    Param.Free;
end;
result:=HTML;
end;

=============================================================================================

 

使用Indy9+D7实现CSDN论坛的登录,回复,发贴,发短信功能

 

代码片断:
  const
   LoginUrl='http://www.csdn.net/member/logon.asp';
   PostUrl='http://community.csdn.net/Expert/PostNew_SQL.asp';
   ReplyUrl='http://community.csdn.net/Expert/reply.asp';
   MsgUrl='http://community.csdn.net/message_board/postsend.asp';
  MyCookList:全局变量,取得当前用户的Cookie
  IdHTTP1: TIdHTTP;
  登录:
  function Logon(UserName, PassWord, CookieTime: string):boolean;
  var
   LoginInfo: TStrings;
   Response: TStringStream;
   i: Integer;
   Cookie:string;
  begin
   Result :=False;
   Cookie:='';
   MyCookList :='';
   Response := TStringStream.Create('');
   LoginInfo := TStringList.Create;
   try
   LoginInfo.Clear;
   LoginInfo.Add('login_name='+UserName);
   LoginInfo.Add('password='+PassWord);
   LoginInfo.Add('from=http://community.csdn.net/Expert/Forum.asp');
   LoginInfo.Add('cookietime='+CookieTime);
   LoginInfo.Add('x=0');
   LoginInfo.Add('y=0'); 
   IdHTTP1.Request.Referer:='http://www.csdn.net/member/logon.asp';
   IdHTTP1.Request.From :='http://community.csdn.net/Expert/Forum.asp';
   try
   IdHTTP1.Post(LoginUrl,LoginInfo,Response);
   except
   showmessage('登陆失败');
   end;
   showmessage(Response.DataString);
   //从返回的页面中找出cookie
   for i :=0 to IdHTTP1.Response.RawHeaders.Count-1 do
   begin
   if UpperCase(Copy(IdHTTP1.Response.RawHeaders[i],1,10)) = 'SET-COOKIE' then
   begin
   Cookie :=Trim(Copy(IdHTTP1.Response.RawHeaders[i],12,MAXINT));
   Cookie :=Copy(Cookie,1,Pos(';',Cookie));
   MyCookList :=MyCookList+Cookie;
   // showmessage(Cookie);
   end;
   end;
   IdHTTP1.Request.RawHeaders.Add('Cookie: '+MyCookList);
   finally
   LoginInfo.Free;
   Response.Free;
   end;
   if length(MyCookList)>200 then
   result:=True;
  end;
  //回复
  function Reply(TopicID, Content: string): boolean;
  var
   ReplyInfo: TStrings;
   Response: TStringStream;
  begin
   Result :=False;
   ReplyInfo := TStringList.Create;
   Response :=TStringStream.Create(''); 
   try
   begin
   //取回复页面
   ReplyInfo.Clear;
   ReplyInfo.Add('Topicid='+TopicID);
   ReplyInfo.Add('xmlReply=aaaaa');
   ReplyInfo.Add('csdnname='); 
   ReplyInfo.Add('csdnpassword=');
   ReplyInfo.Add('ReplyContent='+Content);
   IdHTTP1.Request.CustomHeaders.Add('Cookie: '+copy(MyCookList,1,length(MyCookList)-1)); 
   IdHTTP1.Request.Referer :='http://community.csdn.net/Expert/xsl/Reply_Xml.asp Topicid='+TopicID;
   IdHTTP1.Request.UserAgent:='Redhat/9.0';
   try
   IdHTTP1.Post(ReplyUrl,ReplyInfo,Response);
   except
   showmessage('回复失败');
   exit;
   end;
   // showmessage(Response.DataString);
   if pos('添加完成,正在生成静态页面,请稍候',Response.DataString)>0 then
   Result :=true;
   end;
   finally
   ReplyInfo.Free;
   Response.Free;
   end;
  end;
  //发贴
  function PostNew(RoomID, Point, TopicName,
   Content: string): boolean;
  var
   PostInfo: TStrings;
   Response: TStringStream;
  begin
   Result :=False;
   PostInfo := TStringList.Create;
   Response :=TStringStream.Create(''); 
   try
   begin
   //取发贴页面
   //typestate=1&Point=20&TopicName=test&Room=1404&Content=111222
   PostInfo.Clear;
   PostInfo.Add('typestate=1');
   PostInfo.Add('Point='+Point);
   PostInfo.Add('TopicName='+TopicName);
   PostInfo.Add('Room='+RoomID);
   PostInfo.Add('Content='+Content);
   IdHTTP1.Request.CustomHeaders.Add('Cookie: '+copy(MyCookList,1,length(MyCookList)-1));
   IdHTTP1.Request.CacheControl:='no-cache'; 
   IdHTTP1.Request.UserAgent:='Windows Advanced Server/5.0';
   try
   IdHTTP1.Post(PostUrl,PostInfo,Response);
   except
   showmessage('发帖失败');
   exit;
   end;
   // showmessage(Response.DataString);
   if pos('增加成功,请稍候,正在生成静态页面',Response.DataString)>0 then
   Result :=true;
   end;
   finally
   PostInfo.Free;
   Response.Free;
   end;
  end;
  //发短信
  function SendMsg(SendTo, Content: string): boolean;
  var
   PostInfo: TStrings;
   Response: TStringStream;
  begin
   Result :=False;
   PostInfo := TStringList.Create;
   Response :=TStringStream.Create(''); 
   try
   begin
   PostInfo.Clear;
   PostInfo.Add('Sendto='+SendTo);
   PostInfo.Add('Content='+Content);
   IdHTTP1.Request.CustomHeaders.Add('Cookie: '+copy(MyCookList,1,length(MyCookList)-1));
   try
   IdHTTP1.Post(MsgUrl,PostInfo,Response);
   except
   showmessage('发送失败');
   exit;
   end;
   // showmessage(Response.DataString);
   if pos('发送成功',Response.DataString)>0 then
   Result :=true;
   end;
   finally
   PostInfo.Free;
   Response.Free;
   end;
  end;


=============================================================================================

posted @ 2015-12-21 13:51  tc310  阅读(666)  评论(0编辑  收藏  举报