本帖最后由 republican 于 2011-3-12 08:43 编辑
我的目的是使用WinInet分步POST数据。
对于WinInet来说,其Http传输结构如下:
其中,HttpSendRequest就已经包含了发送及接受的过程,不能再在之后调用InternetWriteFile继续发送数据。
如果想分步向服务器传输请求,只能使用HttpSendRequestEx发送数据。但其中有个INTERNET_BUFFERS结构,我不是很明白,所以在此发帖寻求帮助,谢谢。
假设我要提交的Header为"xxxx",内容为"xxx"(代码中有),那么下述代码应该如何修改?附带一篇讲述WinInet传输过程的文章。
(数据没有正确填充,或是结构有问题。)
(去除71行,将发现BufferLength为0,Header没有填充)
#include <WinINet.au3>
#include <array.au3>
;~ typedef struct _INTERNET_BUFFERS {
;~ DWORD dwStructSize;
;~ _INTERNET_BUFFERS *Next;
;~ LPCTSTR lpcszHeader;
;~ DWORD dwHeadersLength;
;~ DWORD dwHeadersTotal;
;~ LPVOID lpvBuffer;
;~ DWORD dwBufferLength;
;~ DWORD dwBufferTotal;
;~ DWORD dwOffsetLow;
;~ DWORD dwOffsetHigh;
;~ } INTERNET_BUFFERS, * LPINTERNET_BUFFERS;
;~ dwStructSize
;~ Size of the structure, in bytes.
;~ Next
;~ Pointer to the next INTERNET_BUFFERS structure.
;~ lpcszHeader
;~ Pointer to a string value that contains the headers. This member can be NULL.
;~ dwHeadersLength
;~ Size of the headers, in TCHARs, if lpcszHeader is not NULL.
;~ dwHeadersTotal
;~ Size of the headers, if there is not enough memory in the buffer.
;~ lpvBuffer
;~ Pointer to the data buffer.
;~ dwBufferLength
;~ Size of the buffer, in TCHARs, if lpvBuffer is not NULL.
;~ dwBufferTotal
;~ Total size of the resource, in bytes.
;~ dwOffsetLow
;~ Reserved; do not use.
;~ dwOffsetHigh
;~ Reserved; do not use.
;~ Global Const $tagINTERNET_BUFFERS = " dword StructSize;" & _
;~ " ptr Next;" & _
;~ " ptr Header;" & _
;~ " dword HeadersLength;" & _
;~ " dword HeadersTotal;" & _
;~ " ptr Buffer;" & _
;~ " dword BufferLength;" & _
;~ " dword BufferTotal;" & _
;~ " dword Offset[2]"
; ====请先填写账号密码
$Name = ""
$PassWord = ""
$Myopen = _WinINet_InternetOpen()
$hConnect = _WinINet_InternetConnect($Myopen,$INTERNET_SERVICE_HTTP,'www.autoitx.com')
$hRequest = _WinINet_HttpOpenRequest($hConnect,'POST',"/logging.php?action=login&loginsubmit=yes&floatlogin=yes&inajax=1",$INTERNET_FLAG_NO_CACHE_WRITE)
$Context = "formhash=17b2166a&referer=http%3A%2F%2Fwww.autoitx.com%2F&loginfield=username&username="&$Name&"&password="&$PassWord&"&&questionid=0&answer="
$Header = "Content-Type: application/x-www-form-urlencoded" & @CRLF & 'Content-Length: '& BinaryLen(StringToBinary($Context))
_WinINet_HttpAddRequestHeaders($hRequest, $Header , $HTTP_ADDREQ_FLAG_ADD + $HTTP_ADDREQ_FLAG_REPLACE) ;我想要的是将本行去除,并去除上行的'Content-Length',全部交由下面的DllStruct处理
; -------- 本过程数据填充不正确
Local $tINTERNET_BUFFERS[2] = [DllStructCreate($tagINTERNET_BUFFERS), DllStructCreate('Char HeaderChar['&StringLen($Header) +1 &'];BYTE DataBuffer['&BinaryLen($Context)&']') ]
DllStructSetData($tINTERNET_BUFFERS[0], "Header", DllStructGetPtr($tINTERNET_BUFFERS[1], 'HeaderChar'))
DllStructSetData($tINTERNET_BUFFERS[0], "Buffer", DllStructGetPtr($tINTERNET_BUFFERS[1], 'DataBuffer'))
DllStructSetData($tINTERNET_BUFFERS[0], "HeadersLength", StringLen($Header))
DllStructSetData($tINTERNET_BUFFERS[0], "BufferLength", BinaryLen($Context))
DllStructSetData($tINTERNET_BUFFERS[1], "HeaderChar", $Header)
DllStructSetData($tINTERNET_BUFFERS[1], "DataBuffer", $Context)
DllStructSetData($tINTERNET_BUFFERS[0], "StructSize", DllStructGetSize($tINTERNET_BUFFERS[0]))
; ---End Of StructCreate
_WinINet_HttpSendRequestEx($hRequest, $tINTERNET_BUFFERS[0])
ConsoleWrite(_WinAPI_GetLastError()& '----' )
_WinINet_InternetWriteFile($hRequest, StringToBinary($Context))
ConsoleWrite(_WinAPI_GetLastError()& '----' )
_WinINet_HttpEndRequest($hRequest)
ConsoleWrite(_WinAPI_GetLastError()& '----' )
$rContext = _WinINet_HttpQueryInfo($hRequest,$HTTP_QUERY_RAW_HEADERS_CRLF)
MsgBox(64,"Set-Cookies",_WinInet_DecodeHeader($rContext))
$Test = _WinINet_InternetReadFile($hRequest,1024 * 64)
MsgBox(0,"网页内容:",BinaryToString($Test))
_WinINet_InternetCloseHandle($hRequest)
; ===下次执行前,请最好在IE中注销登录
_WinINet_InternetCloseHandle($hConnect)
_WinINet_InternetCloseHandle($Myopen)
Func _WinInet_DecodeHeader($HeaderArray)
Local $t,$UTF_16_Text
$t = DllStructCreate('BYTE TEST['&$HeaderArray[1]&']',DllStructGetPtr($HeaderArray[0]))
$UTF_16_Text = DllStructGetData($t,1)
Return BinaryToString($UTF_16_Text,2)
EndFunc
Func _WinAPI_GetLastError($curErr=@error, $curExt=@extended)
Local $aResult = DllCall("kernel32.dll", "dword", "GetLastError")
Return SetError($curErr, $curExt, $aResult[0])
EndFunc ;==>_WinAPI_GetLastError
|