这两天做了使用HTTPS协议上传、下载文件的项目,终于折腾通了。在此贴上代码,便于自己学习,也许还能帮助遇到类似问题 的人。
//1、HTTP/HTTPS下载文件
bool Download(LPCTSTR strFileURLInServer, //待下载文件的URL
LPCTSTR strFileLocalFullPath)//存放到本地的路径
{
ASSERT(strFileURLInServer != "");
ASSERT(strFileLocalFullPath != "");
CInternetSession session;
CHttpConnection* pHttpConnection = NULL;
CHttpFile* pHttpFile = NULL;
CString strServer, strObject;
INTERNET_PORT wPort;
DWORD dwType, dwFlags;
const int nTimeOut = 2000;
session.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, nTimeOut); //重试之间的等待延时
session.SetOption(INTERNET_OPTION_CONNECT_RETRIES, 1); //重试次数
char* pszBuffer = NULL;
AfxParseURL(strFileURLInServer, dwType, strServer, strObject, wPort);
dwFlags = 0;
if (dwType == AFX_INET_SERVICE_HTTPS)
{
dwFlags = 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;
}
try
{
pHttpConnection = session.GetHttpConnection(strServer, wPort);
pHttpFile = pHttpConnection->OpenRequest(CHttpConnection::HTTP_VERB_GET, strObject,
NULL, 1, NULL, NULL, dwFlags);
if (dwType == AFX_INET_SERVICE_HTTPS)
{
//忽略证书
pHttpFile->QueryOption(INTERNET_OPTION_SECURITY_FLAGS, dwFlags);
dwFlags |= (SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
SECURITY_FLAG_IGNORE_UNKNOWN_CA |
SECURITY_FLAG_IGNORE_WRONG_USAGE |
SECURITY_FLAG_IGNORE_REVOCATION);
//set web server option
BOOL s = pHttpFile->SetOption(INTERNET_OPTION_SECURITY_FLAGS, dwFlags);
}
if(pHttpFile->SendRequest() == FALSE)
return false;
DWORD dwStateCode;
pHttpFile->QueryInfoStatusCode(dwStateCode);
if(dwStateCode == HTTP_STATUS_OK)
{
HANDLE hFile = CreateFile(strFileLocalFullPath, GENERIC_WRITE,
FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
NULL); //创建本地文件
if(hFile == INVALID_HANDLE_VALUE)
{
pHttpFile->Close();
pHttpConnection->Close();
session.Close();
return false;
}
char szInfoBuffer[1000]; //返回消息
DWORD dwFileSize = 0; //文件长度
DWORD dwInfoBufferSize = sizeof(szInfoBuffer);
BOOL bResult = FALSE;
bResult = pHttpFile->QueryInfo(HTTP_QUERY_CONTENT_LENGTH,
(void*)szInfoBuffer,&dwInfoBufferSize,NULL);
dwFileSize = atoi(szInfoBuffer);
const int BUFFER_LENGTH = 1024 * 10;
pszBuffer = new char[BUFFER_LENGTH]; //读取文件的缓冲
DWORD dwWrite, dwTotalWrite;
dwWrite = dwTotalWrite = 0;
UINT nRead = pHttpFile->Read(pszBuffer, BUFFER_LENGTH); //读取服务器上数据
while(nRead > 0)
{
WriteFile(hFile, pszBuffer, nRead, &dwWrite, NULL); //写到本地文件
dwTotalWrite += dwWrite;
nRead = pHttpFile->Read(pszBuffer, BUFFER_LENGTH);
}
delete[]pszBuffer;
pszBuffer = NULL;
CloseHandle(hFile);
}
else
{
delete[]pszBuffer;
pszBuffer = NULL;
if(pHttpFile != NULL)
{
pHttpFile->Close();
delete pHttpFile;
pHttpFile = NULL;
}
if(pHttpConnection != NULL)
{
pHttpConnection->Close();
delete pHttpConnection;
pHttpConnection = NULL;
}
session.Close();
return false;
}
}
catch(...)
{
delete[]pszBuffer;
pszBuffer = NULL;
if(pHttpFile != NULL)
{
pHttpFile->Close();
delete pHttpFile;
pHttpFile = NULL;
}
if(pHttpConnection != NULL)
{
pHttpConnection->Close();
delete pHttpConnection;
pHttpConnection = NULL;
}
session.Close();
return false;
}
if(pHttpFile != NULL)
pHttpFile->Close();
if(pHttpConnection != NULL)
pHttpConnection->Close();
session.Close();
return true;
}
//2、HTTP/HTTPS上传文件UploadFile();
CString MakeRequestHeaders(CString &strBoundary)//包头
{
CString strFormat;
CString strData;
strFormat = _T("Content-Type: multipart/form-data; boundary=%s\r\n");
strData.Format(strFormat, strBoundary);
return strData;
}
CString MakePreFileData(CString &strBoundary, CString &strFileName, int iRecordID)
{
CString strFormat;
CString strData;
strFormat += _T("--%s");
strFormat += _T("\r\n");
strFormat += _T("Content-Disposition: form-data; name=\"fuck\"");
strFormat += _T("\r\n\r\n");
strFormat += _T("jump");
strFormat += _T("\r\n");
strFormat += _T("--%s");
strFormat += _T("\r\n");
strFormat += _T("Content-Disposition: form-data; name=\"fileupload\"; filename=\"%s\"");//文件地址信息
strFormat += _T("\r\n");
strFormat += _T("Content-Type: application/octet-stream");
strFormat += _T("\r\n\r\n");
//strData.Format(strFormat, strBoundary, strFileName);
strData.Format(strFormat, strBoundary,strBoundary, strFileName);
return strData;
}
CString MakePostFileData(CString &strBoundary)//发送请求包
{
CString strFormat;
CString strData;
strFormat = _T("\r\n\r\n");
strFormat += _T("--%s--");
strFormat += _T("\r\n");
strData.Format(strFormat, strBoundary, strBoundary);
return strData;
}
BOOL UploadFile(LPCTSTR fileUrl, LPCTSTR file)
{
CInternetSession Session;
CHttpConnection *pHttpConnection = NULL;
INTERNET_PORT nPort;
CFile fTrack;
CHttpFile* pHTTP;
CString strHTTPBoundary;
CString strPreFileData;
CString strPostFileData;
DWORD dwTotalRequestLength;
DWORD dwChunkLength;
DWORD dwReadLength;
DWORD dwResponseLength;
TCHAR szError[MAX_PATH];
void* pBuffer;
LPSTR szResponse;
CString strResponse;
BOOL bSuccess = TRUE;
CString localFile;
DWORD dwServiceType, dwFlags;
localFile = file;//要传的本地文件地址
int startp = localFile.ReverseFind('\\');
int namelen = localFile.GetLength()-startp-1;
CString pcmname = localFile;
CString defServerName;//服务器名
CString defObjectName;//保存的地址
CString serverPath = fileUrl;
AfxParseURL(serverPath, dwServiceType, defServerName, defObjectName, nPort);
dwFlags = 0;
if (dwServiceType == AFX_INET_SERVICE_HTTPS)
{
dwFlags = 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;
}
CString strDebugMessage;
if(FALSE == fTrack.Open(localFile, CFile::modeRead | CFile::shareDenyWrite))//读出文件
{
return FALSE;
}
int iRecordID = 1;
strHTTPBoundary = _T("-------------2389jhrwfjsjd9823");//定义边界值
strPreFileData = MakePreFileData(strHTTPBoundary, pcmname, iRecordID);
strPostFileData = MakePostFileData(strHTTPBoundary);
dwTotalRequestLength = strPreFileData.GetLength() + strPostFileData.GetLength() + fTrack.GetLength();//计算整个包的总长度
dwChunkLength = 64 * 1024;
pBuffer = malloc(dwChunkLength);
if (NULL == pBuffer)
{
return FALSE;
}
try
{
pHttpConnection = Session.GetHttpConnection(defServerName,nPort);
pHTTP = pHttpConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST, defObjectName,
NULL, 1, NULL, NULL, dwFlags);
if (dwServiceType == AFX_INET_SERVICE_HTTPS)
{
//忽略证书
pHTTP->QueryOption(INTERNET_OPTION_SECURITY_FLAGS, dwFlags);
dwFlags |= (SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
SECURITY_FLAG_IGNORE_UNKNOWN_CA |
SECURITY_FLAG_IGNORE_WRONG_USAGE |
SECURITY_FLAG_IGNORE_REVOCATION);
//set web server option
BOOL s = pHTTP->SetOption(INTERNET_OPTION_SECURITY_FLAGS, dwFlags);
}
pHTTP->AddRequestHeaders(MakeRequestHeaders(strHTTPBoundary));//发送包头请求
pHTTP->SendRequestEx(dwTotalRequestLength, HSR_SYNC | HSR_INITIATE);
#ifdef _UNICODE
pHTTP->Write(W2A(strPreFileData), strPreFileData.GetLength());
#else
pHTTP->Write((LPSTR)(LPCSTR)strPreFileData, strPreFileData.GetLength());//写入服务器所需信息
#endif
dwReadLength = -1;
while (0 != dwReadLength)
{
strDebugMessage.Format(_T("%u / %u\n"), fTrack.GetPosition(), fTrack.GetLength());
TRACE(strDebugMessage);
dwReadLength = fTrack.Read(pBuffer, dwChunkLength);//文件内容
if (0 != dwReadLength)
{
pHTTP->Write(pBuffer, dwReadLength);//写入服务器本地文件,用二进制进行传送
}
}
#ifdef _UNICODE
pHTTP->Write(W2A(strPostFileData), strPostFileData.GetLength());
#else
pHTTP->Write((LPSTR)(LPCSTR)strPostFileData, strPostFileData.GetLength());
#endif
pHTTP->EndRequest(HSR_SYNC);
dwResponseLength = pHTTP->GetLength();
while (0 != dwResponseLength)
{
szResponse = (LPSTR)malloc(dwResponseLength + 1);
szResponse[dwResponseLength] = '\0';
pHTTP->Read(szResponse, dwResponseLength);
strResponse += szResponse;
free(szResponse);
dwResponseLength = pHTTP->GetLength();
}
}
catch (CException* e)
{
e->GetErrorMessage(szError, MAX_PATH);
e->Delete();
AfxMessageBox(szError);
bSuccess = FALSE;
}
pHTTP->Close();
delete pHTTP;
fTrack.Close();
if (NULL != pBuffer)
{
free(pBuffer);
}
return bSuccess;
}