Voglio inviare una richiesta HTTP Post in Delphi 2010 utilizzando WinInet, ma il mio script non funziona; /
È il mio script Delphi:
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(hURLnil) then hRequest := HttpOpenRequest(hURL, 'POST', PChar('test=test'),'HTTP/1.0',PChar(''), nil, INTERNET_FLAG_RELOAD or INTERNET_FLAG_PRAGMA_NOCACHE,0); if(hRequestnil) then HttpSendRequest(hRequest, nil, 0, nil, 0); InternetCloseHandle(hNet); except ShowMessage('error'); end end; end;
e il mio script PHP:
$data = $_POST['test']; $file = "test.txt"; $fp = fopen($file, "a"); flock($fp, 2); fwrite($fp, $data); flock($fp, 3); fclose($fp);
Problemi principali:
Il secondo parametro di InternetConnect
dovrebbe contenere solo il nome del server, non l’intero URL dello script sul lato server.
Il terzo parametro di HttpOpenRequest
dovrebbe essere il nome del file (URL) dello script, non i dati POST!
I dati POST effettivi dovrebbero essere il quarto parametro di HttpSendRequest
.
Problemi minori
INTERNET_OPEN_TYPE_PRECONFIG or INTERNET_OPEN_TYPE_PRECONFIG
: è sufficiente con INTERNET_OPEN_TYPE_PRECONFIG
.
DWORD(0)
è eccessivo. 0
è sufficiente.
Codice d’esempio
Io uso il seguente codice per i dati POST:
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;
Per esempio:
WebPostData('My UserAgent', 'www.rejbrand.se', 'mydir/myscript.asp', 'value=5');
Aggiornamento in risposta alla risposta di OP
Per leggere i dati da Internet, utilizzare InternetReadFile
funzione InternetReadFile
. Io uso il seguente codice per leggere un piccolo file di testo (su una riga) da 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;
Esempio di utilizzo:
WebGetData('My UserAgent', 'www.rejbrand.se', '/MyDir/update/ver.txt')
Questa funzione pertanto legge solo i dati, senza alcun POST precedente. Tuttavia, la funzione InternetReadFile
può anche essere utilizzata con un handle creato da HttpOpenRequest
, quindi funzionerà anche nel tuo caso. Sai che il riferimento WinInet è MSDN, giusto? Tutte le funzioni dell’API di Windows sono descritte in dettaglio qui, ad esempio InternetReadFile .
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;
Esiste una libreria (chiamata “componente HTTPGet per Delphi 32”) su http://www.utilmind.com . Installa un controllo visivo nella tavolozza dei componenti. Fa esattamente quello che vuoi, quindi potresti voler dare un’occhiata.