对于HTTP操作,很多人在不同的语言中用过各种各样的方式 Socket 、Indy 、ICS、WebRequest、HttpClient。。。等等,今天说一种从win xp到win 11都适合的windows WinINet库 的api函数的方式。这是windows系统自带的API。俺用这种方式写的dll 和 exe 现在已经有20多年了,还在全球各个地方每天大量使用。
下载
cpp
bool CHttpTransport::DownloadHttpfile( CString url, CString fileName, DWORD dwFileSize)
{
DWORD dwOrgFileSize = 0;
DWORD dwDownLoadSize = 0;
bool bFileExists = false;
//Is it http address
bool bHttp;
if(!SUCCEEDED(IsHttpUrl(&bHttp,url)))
return false;
//Is it secure http
bool bHttps;
if(!SUCCEEDED(IsHttps(&bHttps,url)))
return false;
//Get server name and suburl
CString serverName,suburl,port;
if(!SUCCEEDED(GetSeverNameAndSubName(url,serverName,suburl,port)))
return false;
LPSTR lpPort = port.GetBuffer();
int iPort = (port == "")?INTERNET_DEFAULT_HTTP_PORT:atoi(lpPort);
HINTERNET hSession = InternetOpen( "HttpSendRequest", INTERNET_OPEN_TYPE_PRECONFIG,NULL, NULL, 0);
if(!hSession)
return false;
//Open http connection to download file
HINTERNET hConnect;
char login[50] = WEBIISUSERNAME;
char pwd[50] = WEBPASSWORD;
if ( bHttps )
hConnect = InternetConnect(hSession, serverName, INTERNET_DEFAULT_HTTPS_PORT,
login, pwd, INTERNET_SERVICE_HTTP,NULL, NULL);
else
hConnect = InternetConnect(hSession, serverName, iPort,
login, pwd, INTERNET_SERVICE_HTTP,NULL, NULL);
if (!hConnect)
return AtlHresultFromLastError();
else
{
DWORD dwTimeOut = 6000;
InternetSetOption(hConnect, INTERNET_OPTION_RECEIVE_TIMEOUT, &dwTimeOut, sizeof(DWORD));
HINTERNET hRequest = NULL;
if ( bHttps )
hRequest = HttpOpenRequest(hConnect, "GET", suburl,
NULL, NULL, NULL, INTERNET_FLAG_SECURE | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, 0);
else
hRequest = HttpOpenRequest(hConnect, "GET", suburl,
NULL, NULL, NULL, INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, 0);
if (!hRequest)
return AtlHresultFromLastError();
CString ErrMsg;
if(!HttpSendRequest( hRequest, NULL, 0, NULL, 0))
return false;
DWORD dwCode = 0;
DWORD dwSize = sizeof(dwCode);
if ( !HttpQueryInfo (hRequest, HTTP_QUERY_STATUS_CODE |
HTTP_QUERY_FLAG_NUMBER, &dwCode, &dwSize, NULL))
return false;
if ( dwCode >= 400)
return false;
HANDLE hFile;
if (dwFileSize > 0)
{
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
hFind = FindFirstFile(fileName, &FindFileData);
if (hFind != INVALID_HANDLE_VALUE)
{
bFileExists = true;
FindClose(hFind);
}
}
if (bFileExists)
{
hFile = CreateFile ( fileName, GENERIC_WRITE, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
dwOrgFileSize = GetFileSize(hFile, NULL);
dwDownLoadSize = dwOrgFileSize;
SetFilePointer(hFile, dwDownLoadSize, NULL, FILE_BEGIN);
}
else
{
hFile = CreateFile ( fileName, GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
}
if (hFile == INVALID_HANDLE_VALUE)
return false;
char pBuffer[100];
BOOL bWrite;
DWORD dwBytesRead = 1;
DWORD dwBytesWritten;
while (dwBytesRead)
{
if(!InternetReadFile(hRequest, pBuffer, 99, &dwBytesRead))
break;
pBuffer[dwBytesRead] = 0;
if (dwBytesRead>0)
{
if (!(bWrite = WriteFile (hFile, pBuffer, dwBytesRead,&dwBytesWritten, NULL)))
break;
dwDownLoadSize += dwBytesWritten;
}
}
CloseHandle(hFile);
if (!InternetCloseHandle(hRequest))
return false;
}
if(!InternetCloseHandle(hConnect))
return false;
if( InternetCloseHandle( hSession ) == FALSE )
return false;
if (dwFileSize > 0 && dwFileSize > dwDownLoadSize)
return false;
return true;
}
delphi版的下载
Delphi
function TxxxxxxxReport.DownloadFile(const remoteurl: string; Stream: TStream;
DownloadTitle: string): Boolean;
var
NetHandle: HINTERNET;
UrlHandle: HINTERNET;
BytesRead: DWORD;
Buffer: array[1..8192] of Char;
HaveRead: DWORD;
lpdwlen, lpdwidx, lpdword: DWord;
begin
Result := false;
NetHandle := InternetOpen(
'hfghfghfg 我爱啃猪脚',
INTERNET_OPEN_TYPE_DIRECT,
nil,
nil,
0);
if Assigned(NetHandle) then begin
UrlHandle := InternetOpenUrl(
NetHandle,
PChar(remoteurl),
nil,
0,
INTERNET_FLAG_RELOAD,
0);
if Assigned(UrlHandle) then
begin
HaveRead := 0;
lpdword := 0;
lpdwlen := 4;
lpdwidx := 0;
HttpQueryInfo(UrlHandle, HTTP_QUERY_CONTENT_LENGTH or HTTP_QUERY_FLAG_NUMBER, @lpdword, lpdwlen, lpdwidx);
repeat
FillChar(Buffer, 8192, 0);
InternetReadFile(UrlHandle, @Buffer[1], SizeOf(Buffer), BytesRead);
Stream.Write(Buffer[1], bytesread);
HaveRead := HaveRead + bytesread;
hintProgress(DownloadTitle, round(HaveRead * 100 / lpdword));
until BytesRead = 0;
result := true;
hintProgress(DownloadTitle, 0);
end;
InternetCloseHandle(UrlHandle);
end;
InternetCloseHandle(NetHandle);
end;
删除
需要服务端开启WebDev
cpp
bool CHttpTransport::DeleteHttpfile(const CString strHttpFileUrl)
{
//Is it http address
bool bHttp;
if(!SUCCEEDED(IsHttpUrl(&bHttp,strHttpFileUrl)))
return false;
//Is it secure http
bool bHttps;
if(!SUCCEEDED(IsHttps(&bHttps,strHttpFileUrl)))
return false;
//Get server name and suburl
CString serverName,suburl,port;
if(!SUCCEEDED(GetSeverNameAndSubName(strHttpFileUrl,serverName,suburl,port)))
return false;
LPSTR lpPort = port.GetBuffer();
int iPort = (port == "")?INTERNET_DEFAULT_HTTP_PORT:atoi(lpPort);
HINTERNET hSession = InternetOpen("HttpSendRequestEx", INTERNET_OPEN_TYPE_PRECONFIG,NULL, NULL, 0);
if(!hSession)
return false;
HINTERNET hConnect;
char login[50] = WEBIISUSERNAME;
char pwd[50] = WEBPASSWORD;
if ( bHttps )
hConnect = InternetConnect(hSession, serverName, INTERNET_DEFAULT_HTTPS_PORT,
login, pwd, INTERNET_SERVICE_HTTP,NULL, NULL);
else
hConnect = InternetConnect(hSession, serverName, iPort,
login, pwd, INTERNET_SERVICE_HTTP,NULL, NULL);
if (!hConnect)
return false;
else
{
//
HINTERNET hRequest= NULL;
if ( bHttps )
hRequest = HttpOpenRequest(hConnect, "DELETE",suburl,NULL, NULL, NULL, INTERNET_FLAG_SECURE, 0);
else
hRequest = HttpOpenRequest(hConnect, "DELETE",suburl,NULL, NULL, NULL, 0, 0);
//
if(!HttpSendRequest( hRequest, NULL, 0, NULL, 0))
return false;
//
HttpEndRequest(hRequest, NULL, HSR_INITIATE, 0);
//
//
if (!InternetCloseHandle(hRequest))
return false;
if(!InternetCloseHandle(hConnect))
return false;
if( InternetCloseHandle( hSession ) == FALSE )
return false;
return true;
}
}
上传
需要服务端开启WebDev
cpp
bool CHttpTransport::UploadHttpfile(const CString strHttpFileUrl,const CString strDesFile)
{
//Is it http address
bool bHttp;
if(!SUCCEEDED(IsHttpUrl(&bHttp,strHttpFileUrl)))
return false;
//Is it secure http
bool bHttps;
if(!SUCCEEDED(IsHttps(&bHttps,strHttpFileUrl)))
return false;
//Get server name and suburl
CString serverName,suburl,port;
if(!SUCCEEDED(GetSeverNameAndSubName(strHttpFileUrl,serverName,suburl,port)))
return false;
LPSTR lpPort = port.GetBuffer();
int iPort = (port == "")?INTERNET_DEFAULT_HTTP_PORT:atoi(lpPort);
HINTERNET hSession = InternetOpen( "HttpSendRequestEx", INTERNET_OPEN_TYPE_PRECONFIG,NULL, NULL, 0);
// INTERNET_OPEN_TYPE_PROXY, "222.208.20.21","<local>",0);
if(!hSession)
return false;
HINTERNET hConnect;
char login[50] = WEBIISUSERNAME;
char pwd[50] = WEBPASSWORD;
if ( bHttps )
hConnect = InternetConnect(hSession, serverName, INTERNET_DEFAULT_HTTPS_PORT,
login, pwd, INTERNET_SERVICE_HTTP,NULL, NULL);
else
hConnect = InternetConnect(hSession, serverName, iPort,
login, pwd, INTERNET_SERVICE_HTTP,NULL, NULL);
if (!hConnect)
return false;
else
{
INTERNET_BUFFERS BufferIn = {0};
DWORD dwBytesRead;
DWORD dwBytesWritten;
BYTE pBuffer[1024]; // Read from file in 1K chunks
ZeroMemory(pBuffer,1024);
BOOL bRead, bRet;
HANDLE hFile;
BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS );
DWORD dwTimeOut = 6000;
InternetSetOption(hConnect, INTERNET_OPTION_SEND_TIMEOUT, &dwTimeOut, sizeof(DWORD));
HINTERNET hRequest= NULL;
if ( bHttps )
hRequest = HttpOpenRequest(hConnect, "PUT",suburl,NULL, NULL, NULL, INTERNET_FLAG_SECURE, 0);
else
hRequest = HttpOpenRequest(hConnect, "PUT",suburl,NULL, NULL, NULL, 0, 0);
if (!hRequest)
return false;
// This counter keeps track of the number of retries
int iNumTrials = 0;
//--------------------------------------------------------------------------------------------
// The retry goto is to re-try the operation when HttpEndRequest returns error 12032.
//--------------------------------------------------------------------------------------------
retry_after_12032:
hFile = CreateFile (strDesFile, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
return false;
}
BufferIn.dwBufferTotal = GetFileSize (hFile, NULL);
if(!HttpSendRequestEx( hRequest, &BufferIn, NULL, 0, 0))
{
CloseHandle(hFile);
return false;
}
DWORD sum = 0;
do
{
if (!(bRead = ReadFile (hFile, pBuffer, sizeof(pBuffer),&dwBytesRead, NULL)))
break;
if (!(bRet=InternetWriteFile( hRequest, pBuffer, dwBytesRead,&dwBytesWritten)))
break;
sum += dwBytesWritten;
}while (dwBytesRead == sizeof(pBuffer)) ;
CloseHandle (hFile);
if(!HttpEndRequest(hRequest, NULL, 0, 0))
{
TCHAR szBuf[80];
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
//--------------------------------------------------------------------------------------------
// Use the following logic to "retry" after receiving error 12032 from HttpEndRequest
//
// Error 12032 = ERROR_INTERNET_FORCE_RETRY means that you just need to send the request again
//
// Sending request again means that you simply need to call:
//
// HttpSendRequest, InternetWriteFile, HttpEndRequest until HttpEndRequest does not return
// back error 12032.
//
// Since NTLM is a 3-way handshake protocol, it will happen that HttpEndRequest will return
// error 12032 two times and therefore I have the following check.
//
// If error 12032 is returned more than 3 times, then there is some Other error.
//--------------------------------------------------------------------------------------------
if(dw == 12032 && iNumTrials < 3) {
iNumTrials++;
goto retry_after_12032;
}
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
wsprintf(szBuf,
"%s failed with error %d: %s.\n Please check IIS directory security setting, \ntemp directory writeing right setting...",
"Http upload ", dw, lpMsgBuf);
MessageBox(NULL, szBuf, "Error", MB_OK);
LocalFree(lpMsgBuf);
return false;
}
if (!InternetCloseHandle(hRequest))
return false;
}
if(!InternetCloseHandle(hConnect))
return false;
if( InternetCloseHandle( hSession ) == FALSE )
return false;
return true;
}