2

我想获得我用 Delphi 以 HTML 格式发送的 post 值。我正在使用TIdHTTPServer.

我的目标是获取 POST 发送的数据。但有一个问题。我使用如下图所示的工具将其作为“表单数据”发送。捕获 POST 请求。

图片

不幸的是,当我发出与HTML相同的请求时,它看不到 POST。我如何实现这一目标?

procedure TForm1.serviceCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  receiveStream: TStream;
begin
  if ARequestInfo.URI = '/test.php' then
  begin
    if ARequestInfo.Command = 'POST' then
    begin
      receiveStream := ARequestInfo.PostStream;
      if Assigned(receiveStream) then
      begin
        LOG.Lines.Add(ReadStringFromStream(receiveStream));
      end;
      AResponseInfo.ResponseNo := 200;
    end;
  end;
end;

HTML POST 请求(Delphi 没有看到该请求。我的目标是实现这个愿望。)

<form method="post" action="http://localhost:99/test.php"> 
    <input type="hidden" name="test" value="04545">
    <input type="submit" value="send"/>
</form>
4

1 回答 1

5

首先,让我先这样说:

  • if ARequestInfo.Command = 'POST' then应更改为

    if TextIsSame(ARequestInfo.Command, 'POST') then

    或更好

    if ARequestInfo.CommandType = hcPOST then

  • OnCommand...事件处理程序在工作线程的上下文中触发,因此对 UI 的任何访问都必须与主 UI 线程同步。

application/x-www-webform-urlencoded现在,您显示的 HTML 将使用媒体类型将 webform 值发布到 HTTP 服务器。在这种情况TIdHTTPServer.OnCommandGet下,该ARequestInfo.PostStream属性不与该媒体类型一起使用,而是nil. 发布的网络表单值将在and属性中以其原始未解析格式提供,如果属性为 True(默认情况下),则在属性中以已解析格式提供。ARequestInfo.FormParamsARequestInfo.UnparsedParamsARequestInfo.ParamsTIdHTTPServer.ParseParams

试试这个:

procedure TForm1.serviceCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  testValue: string;
begin
  if ARequestInfo.URI <> '/test.php' then
  begin
    AResponseInfo.ResponseNo := 404;
    Exit;
  end;
  if ARequestInfo.CommandType <> hcPOST then
  begin
    AResponseInfo.ResponseNo := 405;
    Exit;
  end;
  testValue := ARequestInfo.Params.Values['test'];
  TThread.Queue(nil,
    procedure
    begin
      LOG.Lines.Add('test: ' + testValue);
    end
  );
  AResponseInfo.ResponseNo := 200;
end;

话虽如此,您的测试工具中的“表单数据”是指multipart/form-data媒体类型。在 HTML 中,如果您想使用该媒体类型发布您的网络表单,您必须在元素的enctype参数中明确声明,例如:<form>

<form method="post" action="http://localhost:99/test.php" enctype="multipart/form-data"> 
    <input type="hidden" name="test" value="04545">
    <input type="submit" value="send"/>
</form>

在这种情况下,TIdHTTPServer当前不支持解析multipart/form-data帖子,因此ARequestInfo.PostStream将不支持nil,提供 webform 的原始字节,以便您可以根据需要手动解析数据。

您可以通过查看属性来区分用于发布网络表单的媒体类型ARequestInfo.ContentType,例如:

procedure TForm1.serviceCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  testValue: string;
  data: string;
begin
  if ARequestInfo.URI <> '/test.php' then
  begin
    AResponseInfo.ResponseNo := 404;
    Exit;
  end;
  if ARequestInfo.CommandType <> hcPOST then
  begin
    AResponseInfo.ResponseNo := 405;
    Exit;
  end;
  if IsHeaderMediaType(ARequestInfo.ContentType, 'application/x-www-form-urlencoded') then
  begin
    testValue := ARequestInfo.Params.Values['test'];
    TThread.Queue(nil,
      procedure
      begin
        LOG.Lines.Add('test: ' + testValue);
      end
    );
    AResponseInfo.ResponseNo := 200;
  end
  else if IsHeaderMediaType(ARequestInfo.ContentType, 'multipart/form-data') then
  begin
    data := ReadStringFromStream(ARequestInfo.PostStream);
    TThread.Queue(nil,
      procedure
      begin
        LOG.Lines.Add('form-data: ' + data);
      end
    );
    AResponseInfo.ResponseNo := 200;
  end else
  begin
    AResponseInfo.ResponseNo := 415;
  end;
end;
于 2020-06-25T17:24:42.000 回答