首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Delphi RestClient 處理 Chunked 流式響應:TIdEventStream 替代 Execute 實現實時解析

     編輯:程式設計疑難解答

問題

OANDA 報價流使用 `Transfer-Encoding: chunked` 持續推送,`RestRequest.Execute` 會阻塞等待結束標志,無法實時處理。

方案:TIdEventStream 事件流


uses IdHTTP, IdGlobal, IdStream;

var
  HTTP: TIdHTTP;
  EventStream: TIdEventStream;
  JsonBuffer: TStringBuilder;

procedure TForm1.StartStream;
begin
  HTTP := TIdHTTP.Create(nil);
  HTTP.HandleRedirects := True;
  HTTP.Request.UserAgent := 'MyApp/1.0';
  
  EventStream := TIdEventStream.Create;
  EventStream.OnWrite := StreamWriteEvent; // 關鍵:每收到一塊數據觸發
  
  HTTP.Get('https://stream-fxtrade.oanda.com/v1/prices?accountId=12345&instruments=EUR_USD', EventStream);
end;

procedure TForm1.StreamWriteEvent(const ABuffer: TIdBytes; AOffset, ACount: Integer; var VResult: Integer);
var
  Chunk: string;
  Json: TJSONObject;
begin
  Chunk := BytesToString(ABuffer, AOffset, ACount, IndyTextEncoding_UTF8);
  JsonBuffer.Append(Chunk);
  
  // 簡單按行分割解析(實際需按 chunked 格式解析)
  while JsonBuffer.Length > 0 do begin
    var LineEnd := JsonBuffer.ToString.IndexOf(#10);
    if LineEnd < 0 then Break;
    var Line := JsonBuffer.ToString.Substring(0, LineEnd).Trim;
    JsonBuffer.Remove(0, LineEnd + 1);
    if Line.IsEmpty then Continue;
    try
      Json := TJSONObject.ParseJSONValue(Line) as TJSONObject;
      if Assigned(Json) then ProcessPriceJson(Json);
    except end;
  end;
  
  VResult := ACount; // 告知 Indy 已處理字節數
end;

關鍵點

  • `TIdEventStream.OnWrite` 替換了默認的流寫入,**數據到達即觸發**,無需等待結束。
  • 需自行處理 **chunked 格式解析**(長度前綴 + 數據 + CRLF),或使用成熟的 HTTP 客戶端庫(如 `Indy` 內建 `TIdHTTP` 支持 chunked 透明解碼,直接獲取解碼後數據)。
  • 實時解析 JSON,推送到 UI/數據庫/消息隊列。

替代方案

  • 使用 `TIdHTTP` 直接 `Get` 到 `TMemoryStream`,配合 `OnWork` 事件輪詢讀取已接收數據(較繁瑣)。
  • 切換到支援流式響應的現代庫(如 `REST.Client` 配合 `TRESTResponse` 的 `ContentStream` 事件,Delphi 11+ 支持較好)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved