【发布时间】:2014-01-28 04:48:23
【问题描述】:
花了几天时间撞墙后,我想我会在这里问。
下面代码的问题是我基本上是在迭代一个目录,在那里上传文件。所有文件都很小,大小约为 1KB,因此这不是大小问题。第一次上传很顺利,所有后续调用都被 winhttp 中断,只发送标头。
代码如下:
BOOL NetworkManager::UploadFileToServer(wchar_t *pszURL, wchar_t *pszFilePath, wchar_t *_pszProxyAddress, wchar_t *pszServerAddress)
{
HINTERNET hSession = NULL,
hConnect = NULL,
hRequest = NULL;
BOOL bResults;
DWORD dwSize = 0;
DWORD dwContentLength = 0;
LPCWSTR pszProxyAddress = 0;
wchar_t wszContentLength[256] = { 0 };
pszProxyAddress = _pszProxyAddress;
printf("Trying to send %S\r\n", pszFilePath);
if(pszProxyAddress != NULL && wcslen(pszProxyAddress) < 4)
{
pszProxyAddress = NULL;
}
HANDLE hFile = CreateFile(pszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
printf("UM: Unable to open the file for sending, aborting...\r\n");
return FALSE;
}
DWORD dwFileSize = GetFileSize(hFile, NULL);
// Use WinHttpOpen to obtain a session handle.
if(pszProxyAddress == NULL)
{
hSession = WinHttpOpen( L"Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
NULL,
WINHTTP_NO_PROXY_BYPASS, 0);
}
else
{
hSession = WinHttpOpen( L"Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko",
WINHTTP_ACCESS_TYPE_NAMED_PROXY,
pszProxyAddress,
WINHTTP_NO_PROXY_BYPASS, 0);
}
// Specify an HTTP server.
if (hSession)
{
hConnect = WinHttpConnect( hSession, _pszServerAddress,
INTERNET_DEFAULT_HTTPS_PORT, 0);
}
else
{
printf("hSession failed, errorcode 0x%08x\r\n", GetLastError());
return FALSE;
}
// Create an HTTP request handle.
if (hConnect)
{
hRequest = WinHttpOpenRequest( hConnect, L"POST", L"upload.php",
NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_SECURE);
}
else
{
printf("hConnect failed, errorcode 0x%08x\r\n", GetLastError());
WinHttpCloseHandle(hSession);
return FALSE;
}
PHEAP_BUFFER pBuf = NULL;
DWORD dwBytesWritten = 0;
// Send a request.
if (hRequest)
{
DWORD options = SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_UNKNOWN_CA ;
bResults = WinHttpSetOption( hRequest, WINHTTP_OPTION_SECURITY_FLAGS , (LPVOID)&options, sizeof (DWORD) );
WinHttpAddRequestHeaders(hRequest, L"Content-Type: multipart/form-data; boundary=----BoundaryXu02", (ULONG) -1L, WINHTTP_ADDREQ_FLAG_ADD);
dwContentLength = strlen(pszFormHeader) + dwFileSize + strlen(pszFinalBoundary);
DWORD dwTotalSent = 0;
pBuf = MemoryManager::AllocateHeapMemory(dwContentLength, 1);
DWORD dwBytesRead = 0;
strcat_s((PCHAR)pBuf->pBuffer, pBuf->dwBufferSize, pszFormHeader);
ReadFile(hFile, &pBuf->pBuffer[strlen(pszFormHeader)], dwFileSize, &dwBytesRead, NULL);
memcpy(&pBuf->pBuffer[strlen(pszFormHeader) + dwFileSize], pszFinalBoundary, strlen(pszFinalBoundary));
wsprintf(wszContentLength, L"Content-Length: %d", dwContentLength);
bResults = WinHttpSendRequest( hRequest, wszContentLength, -1, 0, 0, dwContentLength, 0);
printf("Sending out the request\r\n");
WinHttpWriteData(hRequest, pBuf->pBuffer, pBuf->dwBufferSize, &dwBytesWritten);
}
else
{
printf("hRequest failed, errorcode 0x%08x\r\n", GetLastError());
WinHttpCloseHandle(hSession);
WinHttpCloseHandle(hConnect);
return FALSE;
}
//WinHttpWriteData(hRequest, pBuf->pBuffer, pBuf->dwBufferSize, &dwBytesWritten);
// End the request.
if (bResults)
{
bResults = WinHttpReceiveResponse( hRequest, NULL);
}
else
{
printf("hResults failed, errorcode 0x%08x\r\n");
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
MemoryManager::FreeHeapMemory(pBuf);
return FALSE;
}
WinHttpQueryDataAvailable(hRequest, &dwBytesWritten);
// Close any open handles.
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);
MemoryManager::FreeHeapMemory(pBuf);
CloseHandle(hFile);
DeleteFile(pszFilePath);
return TRUE;
}
这是来自服务器的 access_log:
xxx.xxx.xxx.244 - - [09/Jan/2014:16:39:33 +0200] "POST /upload.php HTTP/1.1" 200 1811 "-" "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
xxx.xxx.xxx.244 - - [09/Jan/2014:16:39:33 +0200] "POST /upload.php HTTP/1.1" 200 295 "-" "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
xxx.xxx.xxx.244 - - [09/Jan/2014:16:39:33 +0200] "POST /upload.php HTTP/1.1" 200 295 "-" "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
xxx.xxx.xxx.244 - - [09/Jan/2014:16:39:33 +0200] "POST /upload.php HTTP/1.1" 200 295 "-" "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
xxx.xxx.xxx.244 - - [09/Jan/2014:16:39:33 +0200] "POST /upload.php HTTP/1.1" 200 295 "-" "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
xxx.xxx.xxx.244 - - [09/Jan/2014:16:39:34 +0200] "POST /upload.php HTTP/1.1" 200 295 "-" "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
xxx.xxx.xxx.244 - - [09/Jan/2014:16:39:34 +0200] "POST /upload.php HTTP/1.1" 200 295 "-" "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
xxx.xxx.xxx.244 - - [09/Jan/2014:16:39:34 +0200] "POST /upload.php HTTP/1.1" 200 295 "-" "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
xxx.xxx.xxx.244 - - [09/Jan/2014:16:39:34 +0200] "POST /upload.php HTTP/1.1" 200 295 "-" "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
xxx.xxx.xxx.244 - - [09/Jan/2014:16:39:34 +0200] "POST /upload.php HTTP/1.1" 200 295 "-" "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
xxx.xxx.xxx.244 - - [09/Jan/2014:16:39:34 +0200] "POST /upload.php HTTP/1.1" 200 295 "-" "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
xxx.xxx.xxx.244 - - [09/Jan/2014:16:39:34 +0200] "POST /upload.php HTTP/1.1" 200 295 "-" "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
xxx.xxx.xxx.244 - - [09/Jan/2014:16:39:34 +0200] "POST /upload.php HTTP/1.1" 200 295 "-" "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
xxx.xxx.xxx.244 - - [09/Jan/2014:16:39:34 +0200] "POST /upload.php HTTP/1.1" 200 295 "-" "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
我完全不知道为什么世界上第一个 POST 成功,但其余的都去 sh*t :(
编辑:
忘记添加标题声明:
char *pszFormHeader = "------BoundaryXu02\r\nContent-Disposition: form-data; name=\"uploaded\"; filename=\"aviconv.dat\"\r\nContent-Type: application/octet-stream\r\n\r\n";
char *pszFinalBoundary = "\r\n------BoundaryXu02--\r\n";
char *pwzContentHeader = "Content-Type: multipart/form-data; boundary=----BoundaryXu02";
wchar_t wszContentLength[256] = { 0 };
【问题讨论】:
-
我的猜测是,
CreateFile第二轮失败,GetFileSize返回 (DWORD)-1。找出为什么。一种可能性:您在发送文件后立即删除文件 - 我认为这可能会干扰当前正在进行的枚举。 -
不。枚举工作正常,而且我已经在调试器下确认 createfile 工作正常,并且所有参数都传递给 WinHTTP,因为它们应该是
-
AllocateMemory是否将缓冲区归零?你strcat在分配后立即进入它,除非第一个字节为零,否则它不会做正确的事情。您可能想改用strcpy或memcpy。 -
AllocateMemory 将缓冲区归零。
-
好的,开始工作了。永远不要低估良好睡眠的力量。我会稍后发布答案
标签: c++ visual-c++ winhttp