MFC利用CHttpFile类实现post数据

模拟postman上传数据,主要是json数据和文件数据

1、post数据json格式

bool PostJsonFile(char*& pData, UINT& dataLen, CString& szError, const CString& szObject ,const CString& szServer, int nPort, LPVOID lpOptional /*= NULL*/, DWORD dwOptionalLen /*= 0*/, PCTSTR szToken)
{
	CInternetSession session(_T("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"), 0);
	CHttpConnection* pConnection = NULL;
	CHttpFile* pFile = NULL;

	try
	{
		DWORD ServerType = 0;
		CString StrServer;
		CString StrObj;
		INTERNET_PORT ServerPort = 0;
		if (AfxParseURL(Url, ServerType, StrServer, StrObj, ServerPort))
		{
			if (AFX_INET_SERVICE_HTTP != ServerType && AFX_INET_SERVICE_HTTPS != ServerType)
			{
				return false;
			}
			if (ServerType == AFX_INET_SERVICE_HTTPS)
			{
				pConnection = session.GetHttpConnection(StrServer, INTERNET_FLAG_SECURE, ServerPort,NULL,NULL);//取得一个Https连接
			}

			if (ServerType == AFX_INET_SERVICE_HTTP)
			{
				pConnection = session.GetHttpConnection(StrServer, ServerPort);//取得一个Https连接
			}
		}

		CHCHttpFile* pFile = pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST, szObject,  
							NULL, 1, NULL, NULL, INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE); 

		 /*设置请求相关参数*/
		//pFile->AddRequestHeaders(_T("Accept: */*,application/json"));//accept请求报头域,表示客户端接受哪些类型的信息  
		//pFile->AddRequestHeaders(_T("Accept-Charset:UTF8"));  
		//pFile->AddRequestHeaders(_T("Accept-Language: zh-CN,zh;q=0.9")); 
		//pFile->AddRequestHeaders(_T("X-Requested-With:XMLHttpRequest"));

		pFile->AddRequestHeaders(_T("Accept:*/*"));
		pFile->AddRequestHeaders(_T("Accept-Charset:UTF8"));
		if (szToken != nullptr && _tcslen(szToken) > 0)
		{
			CString strAccesstoken = _T("access_token: ");
			strAccesstoken += szToken;
			pFile->AddRequestHeaders(strAccesstoken);
		}
		pFile->AddRequestHeaders(_T("Content-Type:application/json"));
		
		pFile->SendRequest(NULL, 0, lpOptional, dwOptionalLen);

		DWORD dwRet;  
		pFile->QueryInfoStatusCode(dwRet);//查询执行状态

		if(dwRet != 200)
		{
			szError.Format(_T("请求失败,HTTP错误码: %d"), dwRet);
			delete pFile;
			return false;
		}

		UINT nBufferPhysicalLen = 16 * 1024;
		pData = new char[nBufferPhysicalLen];
		char* pBuffer = pData;
		UINT nBufferLen = nBufferPhysicalLen - 1;
		UINT nTotalReaded = 0;
		UINT nReaded = 0;
		while ((nReaded = pFile->Read((void*)pBuffer, nBufferLen)) > 0)
		{
			nTotalReaded += nReaded;
			pBuffer += nReaded;

			if (nBufferPhysicalLen - nTotalReaded < 512)
			{ //buffer长度在2M以下时,每次重新申请时长度翻倍;超过2M时,每次加2M
				if (nBufferPhysicalLen < 2 * 1024 * 1024)
				{
					nBufferPhysicalLen *= 2;
				}
				else
				{
					nBufferPhysicalLen += 2 * 1024 * 1024;
				}

				char* pNewData = new char[nBufferPhysicalLen];
				memcpy(pNewData, pData, nTotalReaded);
				nBufferLen = nBufferPhysicalLen - nTotalReaded - 1;
				delete[] pData;
				pData = pNewData;
				pBuffer = pNewData + nTotalReaded;
			}
		}

		dataLen = nTotalReaded;
		pData[nTotalReaded] = '\0';
		dataLen++;
		delete pFile;
	}
	catch (CInternetException* e)
	{
		CString sErrMsg;
		e->GetErrorMessage(sErrMsg.GetBuffer(1024), 1024);
		sErrMsg.ReleaseBuffer();
		szError.Format(_T("%s/%s 请求失败,%s"), szServer,szObject, sErrMsg);
		return false;
	}
	catch (CException* e)
	{
		e->GetErrorMessage(szError.GetBuffer(1024), 1024);
		szError.ReleaseBuffer();
		e->Delete();
		return false;
	}

	return true;
}


bool CMyDlg::PostData()
{
	CJsonObj sJson;
	sJson.AddItem(_T("username"), _T("张三"));
	sJson.AddItem(_T("password"), _T("123"));

	char* pData = NULL;
	UINT uLen = 0;
	CString strError;
	char* utf8Data = NULL;
	int nUft8Len = CGlobal::Ansi2UTF8(sJson.CreateJson(), utf8Data);
	CString sObject(_T("/api/login"));
	CString strServer = _T("127.0.0.1");
	CString strPort = _T("8027");
	int nPort = _tstoi(strPort);

	bool bRet = PostJsonFile(pData, uLen, strError, sObject, strServer, nPort, utf8Data, nUft8Len);
	delete[] utf8Data;
	utf8Data = NULL;
	UTF82TCHAR u2t(pData);
	delete[] pData;
	
	if (!bRet)
	{
		if (strError.IsEmpty())
			OutputDebugString(strError);
		return false;
	}

	CJsonObj resultJson;
	if (resultJson.Load(u2t.Data()) == false)
	{
		return false;
	}

	int nStatus = -1;
	if (!resultJson.ValueEx(_T("status"), nStatus, false) || nStatus < 0)
	{
		return false;
	}

	CHCString strMsg;
	if (nStatus > 0)
	{
		return false;
	}
}

2、post上传文件二进制数据

bool PostUploadFile(LPCTSTR Url,LPCTSTR sAaccess_token, wstring  UploadName, char*& _RetStr, const std::string& _FilePath, wstring strLocalFileName,std::wstring wsGuid)
{
	CInternetSession session("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36", 0);
	CHttpConnection* pConnection = NULL;
	CHttpFile* pFile = NULL;
	try{
		DWORD ServerType = 0;
		CString StrServer;
		CString StrObj;
		INTERNET_PORT ServerPort = 0;
		if (AfxParseURL(Url, ServerType, StrServer, StrObj, ServerPort))
		{
			if (AFX_INET_SERVICE_HTTP != ServerType && AFX_INET_SERVICE_HTTPS != ServerType)
			{
				return false;
			}
			if (ServerType == AFX_INET_SERVICE_HTTPS)
			{
				pConnection = session.GetHttpConnection(StrServer, INTERNET_FLAG_SECURE, ServerPort,NULL,NULL);//取得一个Https连接
			}

			if (ServerType == AFX_INET_SERVICE_HTTP)
			{
				pConnection = session.GetHttpConnection(StrServer, ServerPort);//取得一个Https连接
			}
		
			if (pConnection)
			{
				if (ServerType == AFX_INET_SERVICE_HTTPS)
				{
					pFile = pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST, StrObj, NULL, 1,
						NULL, NULL, INTERNET_FLAG_SECURE |
						INTERNET_FLAG_EXISTING_CONNECT |
						INTERNET_FLAG_RELOAD |
						INTERNET_FLAG_NO_CACHE_WRITE |
						INTERNET_FLAG_IGNORE_CERT_DATE_INVALID |
						INTERNET_FLAG_IGNORE_CERT_CN_INVALID |
						INTERNET_FLAG_NO_COOKIES);//打开请求 ,这几个标识都要加上
				}

				if (ServerType == AFX_INET_SERVICE_HTTP)
				{
					pFile = pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST, StrObj);
				}
				if (pFile)
				{
					/*szBoundary,任意的一个串,用以标识body中的数据*/
					//该串需要够复杂,用以区别当前请求包中的数据
					const char * szBoundary = "----------------------------096304854221961038114493";

					/*构造头部*/
					pFile->AddRequestHeaders("Accept:*/*");
					pFile->AddRequestHeaders("Accept-Encoding:gzip, deflate");
					//pFile->AddRequestHeaders("access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0aW1lU3RhbXAiOjE2NDIwNDM3NTY0NDgsImFjY291bnRJZCI6IjY3NDQ4MDk0OTMxOTAwNzA1OTgifQ.hhIwLw0IoQSitrvy7-V8wclnNokZ_EM1tggBEPaelHk");

					//构造头中的access_token项
					CString szAccesstoken = _T("access_token: ");
					szAccesstoken += sAaccess_token;
					pFile->AddRequestHeaders(szAccesstoken.GetBuffer(0));

					//构造头中的Content-Type项,其中需要填上boundary
					CString szContentType = _T("Content-Type:multipart/form-data; boundary=");
					szContentType += szBoundary;
					pFile->AddRequestHeaders(szContentType.GetBuffer(0));

					/*打开文件,合成每个文件头部数据,取出文件数据,以及合成尾部数据,计算总长度*/
					struct DataInfo
					{
						char* pBuf;
						DWORD BufLen;
						DataInfo()
						{
							ZeroMemory(this, sizeof(DataInfo));
						}
					};

					std::vector<DataInfo> DataInfoList;
					
					wstring strGuid = wsGuid;
					
					char key1[1024] = { 0 };
					sprintf(key1, "\r\n------------------------------096304854221961038114493\r\n"
						"Content-Disposition: form-data;name=\"projectId\" \r\n\r\n%s", UnicodeToUtf8(strGuid).c_str());

					char key2[1024] = { 0 };
					sprintf(key2, "\r\n------------------------------096304854221961038114493\r\n"
						"Content-Disposition: form-data;name=\"needUnZip\" \r\n\r\n%s","false");

					char key3[1024] = { 0 };
					sprintf(key3, "\r\n------------------------------096304854221961038114493\r\n"
						"Content-Disposition: form-data;name=\"depot\" \r\n\r\n%s","release");

					char strconnet[1024];
					sprintf(strconnet, "\r\n------------------------------096304854221961038114493\r\n"
						"Content-Disposition:form-data;name=\"%s\";filename=\"%s\"\r\n"
						"Content-Type:application/zip\r\n\r\n", UnicodeToUtf8(UploadName).c_str(), UnicodeToUtf8(strLocalFileName).c_str());

					string temp = key1;
					temp += key2;
					temp += key3;
					temp += strconnet;

					std::string filePath = _FilePath;
					if (filePath.empty())
					{
						return false;
					}

					DWORD dwTotalBodyLen = 0;
					CFile _File;
					if (_File.Open(filePath.c_str(), CFile::modeRead | CFile::shareDenyWrite | CFile::typeBinary))
					{
						//CString FileName = _File.GetFileName();

						//每个文件的头部信息
						DataInfo preDi;
						preDi.BufLen = strlen(temp.c_str());
						preDi.pBuf = new char[preDi.BufLen];
						memcpy(preDi.pBuf, temp.c_str(), preDi.BufLen);
						DataInfoList.push_back(preDi);

						dwTotalBodyLen += preDi.BufLen;

						//文件内容
						DataInfo ContDi;
						ContDi.BufLen = (DWORD)_File.GetLength();
						ContDi.pBuf = new char[ContDi.BufLen];
						_File.Read(ContDi.pBuf, ContDi.BufLen);
						DataInfoList.push_back(ContDi);

						dwTotalBodyLen += ContDi.BufLen;
					}

					//尾长度
					const char* szEndContent =
						"\r\n"
						"------------------------------096304854221961038114493--\r\n";
					DataInfo EndDi;
					EndDi.BufLen = strlen(szEndContent);
					EndDi.pBuf = new char[EndDi.BufLen];
					memcpy(EndDi.pBuf, szEndContent, EndDi.BufLen);
					DataInfoList.push_back(EndDi);

					dwTotalBodyLen += EndDi.BufLen;

					/*发送数据*/
					pFile->SendRequestEx(dwTotalBodyLen, HSR_SYNC | HSR_INITIATE);
					std::vector<DataInfo>::iterator itInfo = DataInfoList.begin();
					for (; itInfo != DataInfoList.end(); itInfo++)
					{
						pFile->Write(itInfo->pBuf, itInfo->BufLen);
						delete[]itInfo->pBuf;
					}
					pFile->EndRequest(HSR_SYNC);

					/*获取状态*/
					DWORD dwStatusCode = -1;
					pFile->QueryInfoStatusCode(dwStatusCode);
					if (dwStatusCode == HTTP_STATUS_OK)
					{
						//读返回
						_RetStr = new char[(DWORD)pFile->GetLength()];
						pFile->Read(_RetStr, (UINT)pFile->GetLength());

						if (pFile)
						{
							delete pFile;
						}

						if (pConnection)
						{
							delete pConnection;
						}

						session.Close();
						return true;
					}
				}
			}
		}
	}
	catch (CInternetException* e)
	{
		delete e;
	}
	if (pFile)
		delete pFile;
	if (pConnection)
		delete pConnection;
	session.Close();

	return false;
}

你可能感兴趣的:(MFC,CHttpFile,post数据)