如何使用 WinInet 在 Delphi 2010 中发送 HTTP Post 请求

问题描述:

我想使用 WinInet 在 Delphi 2010 中发送 HTTP Post 请求,但我的脚本不起作用;/

I want to send a HTTP Post Request in Delphi 2010 using WinInet, but my script doesn't work ;/

这是我的 Delphi 脚本:

It's my Delphi script:

uses WinInet;
procedure TForm1.Button1Click(Sender: TObject);
var
  hNet,hURL,hRequest: HINTERNET;
begin
  hNet := InternetOpen(PChar('User Agent'),INTERNET_OPEN_TYPE_PRECONFIG or INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if Assigned(hNet) then
  begin
  try
    hURL := InternetConnect(hNet,PChar('http://localhost/delphitest.php'),INTERNET_DEFAULT_HTTP_PORT,nil,nil,INTERNET_SERVICE_HTTP,0,DWORD(0));
    if(hURL<>nil) then
      hRequest := HttpOpenRequest(hURL, 'POST', PChar('test=test'),'HTTP/1.0',PChar(''), nil, INTERNET_FLAG_RELOAD or INTERNET_FLAG_PRAGMA_NOCACHE,0);
    if(hRequest<>nil) then
      HttpSendRequest(hRequest, nil, 0, nil, 0);
    InternetCloseHandle(hNet);
  except
      ShowMessage('error');
    end
  end;
end;

和我的 PHP 脚本:

and my PHP script:

$data = $_POST['test'];
$file = "test.txt";
$fp = fopen($file, "a");
flock($fp, 2);
fwrite($fp, $data);
flock($fp, 3);
fclose($fp);

主要问题:

  • InternetConnect 的第二个参数应该只包含服务器的名称,而不是服务器端脚本的整个 URL.

  • The second parameter of InternetConnect should contain only the name of the server, not the entire URL of the server-side script.

HttpOpenRequest的第三个参数应该是脚本的文件名(URL),不是POST数据!

The third parameter of HttpOpenRequest should be the file name (URL) of the script, not the POST data!

实际的POST数据应该是HttpSendRequest的第四个参数.

The actual POST data should be the forth parameter of HttpSendRequest.

小问题

  • INTERNET_OPEN_TYPE_PRECONFIG 或 INTERNET_OPEN_TYPE_PRECONFIG:INTERNET_OPEN_TYPE_PRECONFIG 就足够了.

DWORD(0) 太过分了.0 就够了.

DWORD(0) is overkill. 0 is enough.

示例代码

我使用以下代码来发布数据:

I use the following code to POST data:

procedure WebPostData(const UserAgent: string; const Server: string; const Resource: string; const Data: AnsiString); overload;
var
  hInet: HINTERNET;
  hHTTP: HINTERNET;
  hReq: HINTERNET;
const
  accept: packed array[0..1] of LPWSTR = (PChar('*/*'), nil);
  header: string = 'Content-Type: application/x-www-form-urlencoded';
begin
  hInet := InternetOpen(PChar(UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  try
    hHTTP := InternetConnect(hInet, PChar(Server), INTERNET_DEFAULT_HTTP_PORT, nil, nil, INTERNET_SERVICE_HTTP, 0, 1);
    try
      hReq := HttpOpenRequest(hHTTP, PChar('POST'), PChar(Resource), nil, nil, @accept, 0, 1);
      try
        if not HttpSendRequest(hReq, PChar(header), length(header), PChar(Data), length(Data)) then
          raise Exception.Create('HttpOpenRequest failed. ' + SysErrorMessage(GetLastError));
      finally
        InternetCloseHandle(hReq);
      end;
    finally
      InternetCloseHandle(hHTTP);
    end;
  finally
    InternetCloseHandle(hInet);
  end;
end;

例如:

WebPostData('My UserAgent', 'www.rejbrand.se', 'mydir/myscript.asp', 'value=5');

更新以响应 OP 的回答

要从 Internet 读取数据,请使用 InternetReadFile 函数.我使用以下代码从互联网上读取一个小的(一行)文本文件:

To read data from the Internet, use InternetReadFile function. I use the following code to read a small (one-line) text file from the Internet:

function WebGetData(const UserAgent: string; const Server: string; const Resource: string): string;
var
  hInet: HINTERNET;
  hURL: HINTERNET;
  Buffer: array[0..1023] of AnsiChar;
  i, BufferLen: cardinal;
begin
  result := '';
  hInet := InternetOpen(PChar(UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  try
    hURL := InternetOpenUrl(hInet, PChar('http://' + Server + Resource), nil, 0, 0, 0);
    try
      repeat
        InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen);
        if BufferLen = SizeOf(Buffer) then
          result := result + AnsiString(Buffer)
        else if BufferLen > 0 then
          for i := 0 to BufferLen - 1 do
            result := result + Buffer[i];
      until BufferLen = 0;
    finally
      InternetCloseHandle(hURL);
    end;
  finally
    InternetCloseHandle(hInet);
  end;
end;

示例用法:

WebGetData('My UserAgent', 'www.rejbrand.se', '/MyDir/update/ver.txt')

这个函数因此只读取数据,没有事先的POST.但是,InternetReadFile 函数也可以与 HttpOpenRequest 创建的句柄一起使用,因此它也适用于您的情况.您确实知道 WinInet 参考是 MSDN,对吗?那里详细描述了所有 Windows API 函数,例如 InternetReadFile.

This function thus only reads data, with no prior POST. However, the InternetReadFile function can also be used with a handle created by HttpOpenRequest, so it will work in your case also. You do know that the WinInet reference is MSDN, right? All Windows API functions are described in detail there, for instance InternetReadFile.