String idhttp-加载页面时获取响应字符串

String idhttp-加载页面时获取响应字符串,string,delphi,idhttp,String,Delphi,Idhttp,我需要在加载页面之前获取接收到的字符串(用于asterix http AMI事件)。 因此,我试图在idHttp的OnWork事件中访问接收到的字符串,但出现错误: var Form2: TForm2; s:TStringStream; procedure TForm2.Button1Click(Sender: TObject); begin s:=TStringStream.Create; idhttp1.Get('http://website.com:8088/asteri

我需要在加载页面之前获取接收到的字符串(用于asterix http AMI事件)。 因此,我试图在idHttp的OnWork事件中访问接收到的字符串,但出现错误:

var
  Form2: TForm2;
  s:TStringStream;

procedure TForm2.Button1Click(Sender: TObject);
begin
  s:=TStringStream.Create;
  idhttp1.Get('http://website.com:8088/asterisk/rawman?action=waitevent&timeout=10',s);
  showmessage(s.DataString); //NO ERROR
end;

procedure TForm2.IdHTTP1Work(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCount: Int64);
begin
      showmessage(s.DataString); //ERROR HERE
end;
更新: 我按照Remy Lebeau的建议创建了自定义类(TAMIStringStream),但仍然得到了一个错误。我做错了什么

unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdBaseComponent, IdComponent,
  IdTCPConnection, IdTCPClient, IdHTTP, cxGraphics, cxControls, cxLookAndFeels,
  cxLookAndFeelPainters, cxContainer, cxEdit, Vcl.StdCtrls, cxTextEdit, cxMemo,
  cxCheckBox;

type
  TAMIStringStream = class(TStringStream)
    FEncoding: TEncoding;
    public
    ReceivedSTR:string;

    function Write(const Buffer; Count: Longint): Longint; override;
  end;

  TForm2 = class(TForm)
    IdHTTP1: TIdHTTP;
    Button1: TButton;
    cxCheckBox1: TcxCheckBox;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;
  s:TAMIStringStream;

implementation

{$R *.dfm}

function TAMIStringStream.Write(const Buffer; Count: Longint): Longint;
var t:string;
begin
  Inherited;

  t := FEncoding.GetString(Bytes, Position - Count, Count);
  form2.memo1.lines.add(t);
  ReceivedSTR := ReceivedSTR + t;
end;


procedure TForm2.Button1Click(Sender: TObject);
begin
  idhttp1.Get('http://website.com:8088/asterisk/rawman?action=login&username=1cami&secret=111');
  s:=TAMIStringStream.Create;
  while cxCheckBox1.Checked do begin
    idhttp1.Get('http://website.com:8088/asterisk/rawman?action=waitevent&timeout=10',s);
  end;
end;

end.

要在服务器的HTTP响应数据仍由
TIdHTTP
下载时获取该数据,您需要编写自己的
TStream
-派生类来覆盖虚拟
TStream.write()
方法,然后您可以将该类的实例传递给
TIdHTTP.get()的
AResponseContent
参数
。您的
Write()
方法可以在数据被“写入”到流中时处理数据(准备好以任意块处理该数据,因为它是实时流)

否则,您将不得不完全跳过
TIdHTTP
,而是使用
TIdTCPClient
,手动实现HTTP协议,以便完全控制读写

“AMI over HTTP”协议文档(请参阅和)显示了如何向AMI发送HTTP请求以及如何轮询事件(是的,使用HTTP时必须轮询事件)。由于轮询在事件传递之前不会返回,因此没有太多理由在运行中读取服务器的响应数据
TIdHTTP.Get()
将一直阻止,直到收到事件,然后您可以根据需要对其进行处理。因此,如果没有自定义流,您的第一种方法应该很好:

procedure TForm2.Button1Click(Sender: TObject);
var
  s: TStringStream;
begin
  idhttp1.Get('http://website.com:8088/asterisk/rawman?action=login&username=1cami&secret=111');
  s := TStringStream.Create;
  try
    while cxCheckBox1.Checked do
    begin
      IdHttp1.Get('http://website.com:8088/asterisk/rawman?action=waitevent&timeout=10', s);
      Memo1.Lines.Add(s.DataString);
      s.Clear;
    end;
  finally
    s.Free;
  end;
end;
或者:

procedure TForm2.Button1Click(Sender: TObject);
var
  s: String;
begin
  idhttp1.Get('http://website.com:8088/asterisk/rawman?action=login&username=1cami&secret=111');
  while cxCheckBox1.Checked do
  begin
    s := IdHttp1.Get('http://website.com:8088/asterisk/rawman?action=waitevent&timeout=10');
    Memo1.Lines.Add(s);
  end;
end;
由于
TIdHTTP
的阻塞性质,我建议将轮询移动到工作线程中:

procedure TMyThread.Execute;
var
  http: TIdHTTP;
  s: String;
begin
  http := TIdHTTP.Create(nil);
  try
    http.Get('http://website.com:8088/asterisk/rawman?action=login&username=1cami&secret=111');
    while not Terminated do
    begin
      s := http.Get('http://website.com:8088/asterisk/rawman?action=waitevent&timeout=10');
      // do something...
    end;
  finally
    http.Free;
  end;
end;

如果HTTP轮询不适合您的需求,您应该考虑使用“AMI over TCP”代替(参见和),并使用<代码> TIDTCPclipse < /代码>。您可以使用计时器或线程来检查传入数据。

要在服务器的HTTP响应数据仍由
TIdHTTP
下载时获取该数据,您需要编写自己的
TStream
-派生类来覆盖虚拟
TStream.write()
方法,然后可以将该类的实例传递给
TIdHTTP.Get()
AResponseContent
参数。您的
Write()
方法可以在数据被“写入”到流中时处理数据(准备好以任意块处理该数据,因为它是实时流)

否则,您将不得不完全跳过
TIdHTTP
,而是使用
TIdTCPClient
,手动实现HTTP协议,以便完全控制读写

“AMI over HTTP”协议文档(请参阅和)显示了如何向AMI发送HTTP请求以及如何轮询事件(是的,使用HTTP时必须轮询事件)。由于轮询在事件传递之前不会返回,因此没有太多理由在运行中读取服务器的响应数据
TIdHTTP.Get()
将一直阻止,直到收到事件,然后您可以根据需要对其进行处理。因此,如果没有自定义流,您的第一种方法应该很好:

procedure TForm2.Button1Click(Sender: TObject);
var
  s: TStringStream;
begin
  idhttp1.Get('http://website.com:8088/asterisk/rawman?action=login&username=1cami&secret=111');
  s := TStringStream.Create;
  try
    while cxCheckBox1.Checked do
    begin
      IdHttp1.Get('http://website.com:8088/asterisk/rawman?action=waitevent&timeout=10', s);
      Memo1.Lines.Add(s.DataString);
      s.Clear;
    end;
  finally
    s.Free;
  end;
end;
或者:

procedure TForm2.Button1Click(Sender: TObject);
var
  s: String;
begin
  idhttp1.Get('http://website.com:8088/asterisk/rawman?action=login&username=1cami&secret=111');
  while cxCheckBox1.Checked do
  begin
    s := IdHttp1.Get('http://website.com:8088/asterisk/rawman?action=waitevent&timeout=10');
    Memo1.Lines.Add(s);
  end;
end;
由于
TIdHTTP
的阻塞性质,我建议将轮询移动到工作线程中:

procedure TMyThread.Execute;
var
  http: TIdHTTP;
  s: String;
begin
  http := TIdHTTP.Create(nil);
  try
    http.Get('http://website.com:8088/asterisk/rawman?action=login&username=1cami&secret=111');
    while not Terminated do
    begin
      s := http.Get('http://website.com:8088/asterisk/rawman?action=waitevent&timeout=10');
      // do something...
    end;
  finally
    http.Free;
  end;
end;

如果HTTP轮询不适合您的需求,您应该考虑使用“AMI over TCP”代替(参见和),并使用<代码> TIDTCPclipse < /代码>。您可以使用计时器或线程来检查传入数据。

要在服务器的HTTP响应数据仍由
TIdHTTP
下载时获取该数据,您需要编写自己的
TStream
-派生类来覆盖虚拟
TStream.write()
方法,然后可以将该类的实例传递给
TIdHTTP.Get()
AResponseContent
参数。您的
Write()
方法可以在数据被“写入”到流中时处理数据(准备好以任意块处理该数据,因为它是实时流)

否则,您将不得不完全跳过
TIdHTTP
,而是使用
TIdTCPClient
,手动实现HTTP协议,以便完全控制读写

“AMI over HTTP”协议文档(请参阅和)显示了如何向AMI发送HTTP请求以及如何轮询事件(是的,使用HTTP时必须轮询事件)。由于轮询在事件传递之前不会返回,因此没有太多理由在运行中读取服务器的响应数据
TIdHTTP.Get()
将一直阻止,直到收到事件,然后您可以根据需要对其进行处理。因此,如果没有自定义流,您的第一种方法应该很好:

procedure TForm2.Button1Click(Sender: TObject);
var
  s: TStringStream;
begin
  idhttp1.Get('http://website.com:8088/asterisk/rawman?action=login&username=1cami&secret=111');
  s := TStringStream.Create;
  try
    while cxCheckBox1.Checked do
    begin
      IdHttp1.Get('http://website.com:8088/asterisk/rawman?action=waitevent&timeout=10', s);
      Memo1.Lines.Add(s.DataString);
      s.Clear;
    end;
  finally
    s.Free;
  end;
end;
或者:

procedure TForm2.Button1Click(Sender: TObject);
var
  s: String;
begin
  idhttp1.Get('http://website.com:8088/asterisk/rawman?action=login&username=1cami&secret=111');
  while cxCheckBox1.Checked do
  begin
    s := IdHttp1.Get('http://website.com:8088/asterisk/rawman?action=waitevent&timeout=10');
    Memo1.Lines.Add(s);
  end;
end;
由于
TIdHTTP
的阻塞性质,我建议将轮询移动到工作线程中:

procedure TMyThread.Execute;
var
  http: TIdHTTP;
  s: String;
begin
  http := TIdHTTP.Create(nil);
  try
    http.Get('http://website.com:8088/asterisk/rawman?action=login&username=1cami&secret=111');
    while not Terminated do
    begin
      s := http.Get('http://website.com:8088/asterisk/rawman?action=waitevent&timeout=10');
      // do something...
    end;
  finally
    http.Free;
  end;
end;

如果HTTP轮询不适合您的需求,您应该考虑使用“AMI over TCP”代替(参见和),并使用<代码> TIDTCPclipse < /代码>。您可以使用计时器或线程来检查传入数据。

要在服务器的HTTP响应数据仍由
TIdHTTP
下载时获取该数据,您需要编写自己的
TStream
-派生类来覆盖虚拟
TStream.write()
方法,然后可以将该类的实例传递给
TIdHTTP.Get()
AResponseContent
参数。您的
Write()
方法可以在数据被“写入”到流中时处理数据(准备好以任意块处理该数据,因为它是实时流)

否则,您将不得不完全跳过
TIdHTTP
,而是使用
TIdTCPClient
,手动实现HTTP协议,以便完全控制读写

“AMIoverHTTP”协议文档(请参阅和)显示了如何向AMI发送HTTP请求以及如何