0

ページが読み込まれる前に受信した文字列を取得する必要があります (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.
4

1 に答える 1

3

によるダウンロード中にサーバーの HTTP 応答データを取得するには、仮想メソッドをオーバーライドTIdHTTPする独自の 派生クラスを作成する必要があります。その後、そのクラスのインスタンスを のパラメータに渡すことができます。メソッドは、データがストリームに「書き込まれる」ときにデータを処理できます (データはライブ ストリーミングであるため、任意のチャンクで処理できるように準備してください) 。TStreamTStream.Write()AResponseContentTIdHTTP.Get()Write()

それ以外の場合は、TIdHTTP完全にスキップしてTIdTCPClient代わりに使用し、HTTP プロトコルを手動で実装して、読み取りと書き込みを完全に制御する必要があります。

「AMI over HTTP」プロトコルのドキュメント (こちらこちらを参照) には、HTTP リクエストを AMI に送信する方法と、イベントをポーリングする方法が示されています (はい、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」を使用することを検討し (これこれを参照)、そのために使用TIdTCPClientしてください。タイマーまたはスレッドを使用して、着信データをチェックできます。

于 2015-08-05T23:14:21.670 に答える