问题
I want to send a HTTP Post Request in Delphi 2010 using WinInet, but my script doesn\'t work ;/
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;
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);
回答1:
Major problems:
The second parameter of
InternetConnectshould contain only the name of the server, not the entire URL of the server-side script.The third parameter of
HttpOpenRequestshould be the file name (URL) of the script, not the POST data!The actual POST data should be the forth parameter of
HttpSendRequest.
Minor problems
INTERNET_OPEN_TYPE_PRECONFIG or INTERNET_OPEN_TYPE_PRECONFIG: It is sufficient withINTERNET_OPEN_TYPE_PRECONFIG.DWORD(0)is overkill.0is enough.
Sample Code
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;
For instance:
WebPostData('My UserAgent', 'www.rejbrand.se', 'mydir/myscript.asp', 'value=5');
Update in response to answer by OP
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;
Sample usage:
WebGetData('My UserAgent', 'www.rejbrand.se', '/MyDir/update/ver.txt')
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.
回答2:
var
BufferIn : INTERNET_BUFFERS;
Buffer: array[0..1024] of Byte;
FTmp: TSomeStream:
FURL: string;
...
begin
... // Create FTmp, set FUrl, ...
NetHandle := InternetOpen( 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3',
INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
UrlHandle := HttpOpenRequest(NetHandle, 'POST', PChar(FURL), nil, nil, nil, INTERNET_FLAG_NO_CACHE_WRITE, 0);
... // Check handles, etc
try
BufferIn.dwBufferTotal := FTmp.Size;
if not HttpSendRequestEx(UrlHandle, @BufferIn, nil, 0, 0) then
raise Exception.CreateFmt('Error on HttpSendRequestEx %d\n', [GetLastError()]);
size := FTmp.Read(Buffer, 1024);
InternetWriteFile(UrlHandle, @Buffer, size, BytesWritten);
while (BytesWritten = size) and (BytesWritten > 0) do
begin
size := FTmp.Read(Buffer, 1024);
InternetWriteFile(UrlHandle, @Buffer, size, BytesWritten);
end;
finally
FTmp.Free;
InternetCloseHandle(UrlHandle);
InternetCloseHandle(NetHandle);
end;
回答3:
There is a library (called 'HTTPGet component for Delphi 32') on http://www.utilmind.com. It installs a visual control into your component palette. It does exactly what you want, so you may want to take a look.
来源:https://stackoverflow.com/questions/2977720/how-to-send-a-http-post-request-in-delphi-2010-using-wininet