以前很常见的一种HTTP操作方式

对于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;
}
相关推荐
约定Da于配置3 小时前
uniapp封装websocket
前端·javascript·vue.js·websocket·网络协议·学习·uni-app
hardWork_yulu5 小时前
Android RTMP直播练习实践
网络·安卓
qq_243050795 小时前
irpas:互联网路由协议攻击套件!全参数详细教程!Kali Linux入门教程!黑客渗透测试!
linux·网络·web安全·网络安全·黑客·渗透测试·系统安全
肖田变强不变秃6 小时前
C++实现矩阵Matrix类 实现基本运算
开发语言·c++·matlab·矩阵·有限元·ansys
chengpei1477 小时前
实现一个自己的spring-boot-starter,基于SQL生成HTTP接口
java·数据库·spring boot·sql·http
大丈夫立于天地间7 小时前
机遇、挑战与融合创新之路
网络
青旋.7 小时前
数据链路层——以太网协议
网络·网络协议·tcp/ip
东锋1.39 小时前
计算机网络中常用的端口号以及对应的应用程序
网络
IpdataCloud9 小时前
如何提升IP地址查询数据服务的安全?
网络·tcp/ip·安全
互联网资讯10 小时前
详解共享WiFi小程序怎么弄!
大数据·运维·网络·人工智能·小程序·生活