使用WinINet
一個較簡單的例子:上傳頭像
void CBackstageManager::UpdateAvatarThreadProc(LPVOID params) { stForThread* pSt = (stForThread* )params; HINTERNET hSession=0; HINTERNET hConnect=0; HINTERNET hRequest=0; DWORD dwNumberOfBytesWritten=0; DWORD dwBytesSend=0; DWORD dwFlag = 0; hSession=InternetOpen(_T("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0"), INTERNET_OPEN_TYPE_PRECONFIG, 0, INTERNET_INVALID_PORT_NUMBER, 0); if (0==hSession) { SAFE_DELETE(pSt); NotifyManager::Instance().Notify(TaskListener::TASK_TYPE_UPDATE_AVATAR_RESULT, TaskListener::TASK_STATUS_TIMEOUT,0); return ; } unsigned short port_ = INTERNET_DEFAULT_HTTP_PORT; if (CConfig::IsHttps()) //外網用HTTPS { port_ = INTERNET_DEFAULT_HTTPS_PORT; } //INTERNET_SERVICE_HTTP : HTTP HTTPS hConnect=InternetConnect(hSession, CConfig::URL_HOST, port_, _T(""), _T(""), INTERNET_SERVICE_HTTP, 0, 0); //URL_HOST不能帶http:// if (0==hConnect) { SAFE_DELETE(pSt); NotifyManager::Instance().Notify(TaskListener::TASK_TYPE_UPDATE_AVATAR_RESULT, TaskListener::TASK_STATUS_TIMEOUT,0); InternetCloseHandle(hSession); return ; } dwFlag=INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_AUTH | INTERNET_FLAG_NO_UI ; if (CConfig::IsHttps()) //外網用HTTPS dwFlag |= INTERNET_FLAG_SECURE|INTERNET_FLAG_IGNORE_CERT_CN_INVALID|INTERNET_FLAG_IGNORE_CERT_DATE_INVALID|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP ; hRequest=HttpOpenRequest(hConnect, _T("POST"), UPDATE_AVATAR_URL, HTTP_VERSION, 0, //Referrer 0, //AcceptTypes dwFlag, 0); if (0==hRequest) { InternetCloseHandle(hConnect); InternetCloseHandle(hSession); SAFE_DELETE(pSt); NotifyManager::Instance().Notify(TaskListener::TASK_TYPE_UPDATE_AVATAR_RESULT, TaskListener::TASK_STATUS_TIMEOUT,0); return ; } //設置Header CString content_type = TEXT("Content-Type: multipart/form-data; boundary="); content_type.Append(_T(ABOUNDARY)); HttpAddRequestHeaders(hRequest,content_type,-1,HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE); //驗證cid和token CString szAuthorization = TEXT("Authorization: "); szAuthorization.Append(CBackstageManager::GetInstance().GetAuthorizationString()); HttpAddRequestHeaders(hRequest,szAuthorization, -1,HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE); szAuthorization = TEXT("Agent-Info: "); szAuthorization.Append(CBackstageManager::GetInstance().GetAgentInfo()); HttpAddRequestHeaders(hRequest,szAuthorization, -1,HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE); //讀取文件內容和長度 HANDLE hFile; hFile=CreateFile(pSt->sTmp, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); DWORD dwFileSize=GetFileSize(hFile,0); BYTE* lpBuffer=(BYTE*)VirtualAlloc(0,dwFileSize,MEM_COMMIT,PAGE_READWRITE); if (0==lpBuffer) { InternetCloseHandle(hRequest); InternetCloseHandle(hConnect); InternetCloseHandle(hSession); SAFE_DELETE(pSt); NotifyManager::Instance().Notify(TaskListener::TASK_TYPE_UPDATE_AVATAR_RESULT, TaskListener::TASK_STATUS_ERROR,0); return ; } DWORD dwRead; ReadFile(hFile,lpBuffer,dwFileSize,&dwRead,0); CloseHandle(hFile); char first_boundary[64]={0}; char delimiter[64]={0}; char end_boundary[64]={0}; sprintf_s(first_boundary,"--%s\r\n",ABOUNDARY); sprintf_s(delimiter,"\r\n--%s\r\n",ABOUNDARY); sprintf_s(end_boundary,"\r\n--%s--\r\n",ABOUNDARY); //LPSTR rn="\r\n"; //HTTP POST數據中的換行必須使用\r\n //計算body長度 char content_dispos[64]={0}; int length = strlen(first_boundary); CString stmName = PathFindFileName(pSt->sTmp); char content_dispos2[256]={0}; if(stmName.GetLength() > 32) { stmName = stmName.Left(28) + PathFindExtension(stmName); //防止content_dispos2越界 } std::string name = CT2A(stmName, CP_UTF8); sprintf_s(content_dispos2, "Content-Disposition: form-data; name=\"image\"; filename=\"%s\"\r\n", name.c_str()); LPSTR content_type2="Content-Type: application/octet-stream\r\n\r\n"; //加上File長度 length +=dwFileSize + strlen(content_dispos2) +strlen(content_type2); length += strlen(end_boundary); INTERNET_BUFFERS BufferIn; BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS ); BufferIn.Next = NULL; BufferIn.lpcszHeader = NULL; BufferIn.dwHeadersLength = 0; BufferIn.dwHeadersTotal = 0; BufferIn.lpvBuffer = NULL; BufferIn.dwBufferLength = 0; BufferIn.dwBufferTotal = length; BufferIn.dwOffsetLow = 0; BufferIn.dwOffsetHigh = 0; if (!HttpSendRequestEx(hRequest,&BufferIn,0,0,0)) { DWORD a = GetLastError(); InternetCloseHandle(hRequest); InternetCloseHandle(hConnect); InternetCloseHandle(hSession); SAFE_DELETE(pSt); NotifyManager::Instance().Notify(TaskListener::TASK_TYPE_UPDATE_AVATAR_RESULT, TaskListener::TASK_STATUS_TIMEOUT,0); return ; } //上傳body InternetWriteFile(hRequest,(byte*)first_boundary,strlen(first_boundary),&dwNumberOfBytesWritten); //first boundary //上傳文件 InternetWriteFile(hRequest,(byte*)content_dispos2,strlen(content_dispos2),&dwNumberOfBytesWritten); InternetWriteFile(hRequest,(byte*)content_type2,strlen(content_type2),&dwNumberOfBytesWritten); InternetWriteFile(hRequest,lpBuffer,dwFileSize,&dwNumberOfBytesWritten); //last boundary InternetWriteFile(hRequest,(byte*)end_boundary,strlen(end_boundary),&dwNumberOfBytesWritten); if(!HttpEndRequest(hRequest,0,0,0)) HttpEndRequest(hRequest,0,0,0); VirtualFree(lpBuffer,0,MEM_RELEASE); //獲取返回數據 std::stringstream sstream; CParseResumeTask::GetResponse(&sstream, hRequest, 5000); Json::Value root; Json::Reader reader; reader.parse(sstream.str(), root); int code = -1; if(!root["code"].isNull()) { code = root["code"].asInt(); //0表示成功, } if(!root["msg"].isNull()) { std::string s = root["msg"].asString(); CString sss = CA2T(s.c_str(), CP_UTF8); } CString szAvatarUrl; if(!root["data"].isNull()) { szAvatarUrl = CBackstageManager::GetJsonString(root, "data"); CBackstageManager::GetInstance().SetAvatarDownUrl(szAvatarUrl); } InternetCloseHandle(hRequest); InternetCloseHandle(hConnect); InternetCloseHandle(hSession); if(code == 0) { { CBackstageManager::GetInstance().SetAvatarLocalPath(pSt->sTmp); CSaveAccount::SaveAvatarUrl(CBackstageManager::GetInstance().GetUserId(), szAvatarUrl, pSt->sTmp); } NotifyManager::Instance().Notify(TaskListener::TASK_TYPE_UPDATE_AVATAR_RESULT, TaskListener::TASK_STATUS_OK,0); } else { if (code == 7 || code == 8) CBackstageManager::NotifyUnlogged(code == 8); else NotifyManager::Instance().Notify(TaskListener::TASK_TYPE_UPDATE_AVATAR_RESULT, TaskListener::TASK_STATUS_ERROR,0); } SAFE_DELETE(pSt); }
較麻煩的實例:上傳簡歷文件,及各項參數
int CParseResumeTask::UpdateToServer2(const stResumeInfo& st, int& candId, CString& szUpdateTime, int& nFileSize, int& reposedCode) { HINTERNET hSession=0; HINTERNET hConnect=0; HINTERNET hRequest=0; DWORD dwNumberOfBytesWritten=0; DWORD dwBytesSend=0; DWORD dwFlag = 0; reposedCode = 0; candId = 0; szUpdateTime.Empty(); hSession=InternetOpen(_T("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0"), INTERNET_OPEN_TYPE_PRECONFIG, 0, INTERNET_INVALID_PORT_NUMBER, 0); if (0==hSession) { reposedCode = -1; return 0; } unsigned short port_ = INTERNET_DEFAULT_HTTP_PORT; if (CConfig::GetServerType() == 1) //外網用HTTPS { port_ = INTERNET_DEFAULT_HTTPS_PORT; } hConnect=InternetConnect(hSession, CConfig::URL_HOST, port_, _T(""), _T(""), INTERNET_SERVICE_HTTP, 0, 0); //URL_HOST不能帶http:// if (0==hConnect) { InternetCloseHandle(hSession); reposedCode = -2; return 0; } dwFlag=INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_AUTH | INTERNET_FLAG_NO_UI ; if (CConfig::GetServerType() == 1) //外網用HTTPS dwFlag |= INTERNET_FLAG_SECURE|INTERNET_FLAG_IGNORE_CERT_CN_INVALID|INTERNET_FLAG_IGNORE_CERT_DATE_INVALID|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP ; #ifdef UP_FILE_TO_SEVER hRequest=HttpOpenRequest(hConnect, _T("POST"), RESUME_UPLOAD_URL, HTTP_VERSION, 0, 0, dwFlag, 0);//old #else hRequest=HttpOpenRequest(hConnect, _T("POST"), RESUME_UPLOAD_URL_NEW, HTTP_VERSION, 0, 0, dwFlag, 0); #endif if (0==hRequest) { InternetCloseHandle(hConnect); InternetCloseHandle(hSession); reposedCode = -3; return 0; } if (m_bCancel) return 0; //設置Header //TCHAR content_type[128]={0}; //_stprintf_s(content_type,TEXT("Content-Type: multipart/form-data; boundary=%s"), _T(ABOUNDARY)); CString content_type = TEXT("Content-Type: multipart/form-data; boundary="); content_type.Append(_T(ABOUNDARY)); HttpAddRequestHeaders(hRequest,content_type,-1,HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE); //如果當前用戶ID與預存的用戶ID不一致(已登出,或已登錄新賬戶),不再上傳 int userid = CBackstageManager::GetInstance().GetUserId(); if (m_nCurUserid != userid) return 0; //驗證cid和token CString szAuthorization = TEXT("Authorization: "); szAuthorization.Append(/*CA2T(s64, CP_UTF8)*/CBackstageManager::GetInstance().GetAuthorizationString()); HttpAddRequestHeaders(hRequest,szAuthorization, -1,HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE); szAuthorization = TEXT("Agent-Info: "); szAuthorization.Append(CBackstageManager::GetInstance().GetAgentInfo()); HttpAddRequestHeaders(hRequest,szAuthorization, -1,HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE); #ifdef UP_FILE_TO_SEVER //讀取文件內容和長度 HANDLE hFile; hFile=CreateFile(st.strFilePath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); DWORD dwFileSize=GetFileSize(hFile,0); BYTE* lpBuffer=(BYTE*)VirtualAlloc(0,dwFileSize,MEM_COMMIT,PAGE_READWRITE); if (0==lpBuffer) { InternetCloseHandle(hRequest); InternetCloseHandle(hConnect); InternetCloseHandle(hSession); LOG_INFO(L"----- updateResume VirtualAlloc return 0 !!! GetLastError: %d------", GetLastError()); return 0; } DWORD dwRead; ReadFile(hFile,lpBuffer,dwFileSize,&dwRead,0); CloseHandle(hFile); #endif char first_boundary[64]={0}; char delimiter[64]={0}; char end_boundary[64]={0}; sprintf_s(first_boundary,"--%s\r\n",ABOUNDARY); sprintf_s(delimiter,"\r\n--%s\r\n",ABOUNDARY); sprintf_s(end_boundary,"\r\n--%s--\r\n",ABOUNDARY); //LPSTR rn="\r\n"; //HTTP POST數據中的換行必須使用\r\n std::map<std::string, std::string> ssmap; GetResumeInfoMap(st, ssmap); ////上傳給后台必須使用字符串,不能用整型 //計算body長度 char content_dispos[64]={0}; std::map<std::string, std::string>::iterator it = ssmap.begin(); int length = strlen(first_boundary); for(; it != ssmap.end(); it++) { memset(content_dispos, 0, sizeof(content_dispos)); sprintf_s(content_dispos,"Content-Disposition: form-data; name=\"%s\"\r\n\r\n", it->first.c_str()); length += strlen(content_dispos); length += it->second.length(); length += strlen(delimiter); } #ifdef UP_FILE_TO_SEVER char content_dispos2[256]={0}; CString stmName = st.file_name; if(stmName.GetLength() > 32) { stmName = stmName.Left(28) + PathFindExtension(stmName); //防止content_dispos2越界 } std::string name = CT2A(stmName, CP_UTF8); sprintf_s(content_dispos2, "Content-Disposition: form-data; name=\"file\"; filename=\"%s\"\r\n", name.c_str()); LPSTR content_type2="Content-Type: application/octet-stream\r\n\r\n"; //加上File長度 length +=dwFileSize + strlen(content_dispos2) +strlen(content_type2); #else length -= strlen(delimiter); #endif length += strlen(end_boundary); if (m_bCancel) return FALSE; INTERNET_BUFFERS BufferIn; BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS ); BufferIn.Next = NULL; BufferIn.lpcszHeader = NULL; BufferIn.dwHeadersLength = 0; BufferIn.dwHeadersTotal = 0; BufferIn.lpvBuffer = NULL; BufferIn.dwBufferLength = 0; BufferIn.dwBufferTotal = length; BufferIn.dwOffsetLow = 0; BufferIn.dwOffsetHigh = 0; if (!HttpSendRequestEx(hRequest,&BufferIn,0,0,0)) { InternetCloseHandle(hRequest); InternetCloseHandle(hConnect); InternetCloseHandle(hSession); reposedCode = -4; return 0; } //上傳body InternetWriteFile(hRequest,(byte*)first_boundary,strlen(first_boundary),&dwNumberOfBytesWritten); //first boundary int count = ssmap.size(); std::map<std::string, std::string>::iterator iter = ssmap.begin(); for(int index = 0; iter != ssmap.end(); iter++, index++) { memset(content_dispos, 0, sizeof(content_dispos)); sprintf_s(content_dispos,"Content-Disposition: form-data; name=\"%s\"\r\n\r\n", iter->first.c_str()); InternetWriteFile(hRequest,(byte*)content_dispos, strlen(content_dispos),&dwNumberOfBytesWritten); std::string value = iter->second; InternetWriteFile(hRequest,(byte*)value.c_str(), value.length(), &dwNumberOfBytesWritten); #ifndef UP_FILE_TO_SEVER if(index != (count-1)) #endif InternetWriteFile(hRequest,(byte*)delimiter,strlen(delimiter),&dwNumberOfBytesWritten); } if (m_bCancel) return 0; #ifdef UP_FILE_TO_SEVER //上傳文件 InternetWriteFile(hRequest,(byte*)content_dispos2,strlen(content_dispos2),&dwNumberOfBytesWritten); InternetWriteFile(hRequest,(byte*)content_type2,strlen(content_type2),&dwNumberOfBytesWritten); InternetWriteFile(hRequest,lpBuffer,dwFileSize,&dwNumberOfBytesWritten); #endif //last boundary InternetWriteFile(hRequest,(byte*)end_boundary,strlen(end_boundary),&dwNumberOfBytesWritten); if(!HttpEndRequest(hRequest,0,0,0)) { int a = GetLastError(); HttpEndRequest(hRequest,0,0,0); } #ifdef UP_FILE_TO_SEVER VirtualFree(lpBuffer,0,MEM_RELEASE); #endif if (m_bCancel) return 0; //獲取返回數據 std::stringstream sstream; GetResponse(&sstream, hRequest, 5000); Json::Value root; Json::Reader reader; reader.parse(sstream.str(), root); int code = -1; if(!root["code"].isNull()) { code = root["code"].asInt(); //0表示成功, reposedCode = code; } CString sss; if(!root["msg"].isNull()) { std::string s = root["msg"].asString(); sss = CA2T(s.c_str(), CP_UTF8); } if(!root["data"].isNull()) { Json::Value data = root["data"]; int userId = data["userId"].asInt(); candId = data["candidateId"].asInt(); int resumeId = data["resumeId"].asInt(); nFileSize = data["resumeSize"].asInt(); szUpdateTime = CParseResumeTask::GetJsonString(data, "updateTime"); CString szResuName = CParseResumeTask::GetJsonString(data, "resumeName"); //resumeName=51job_丁奕聰(338664425).doc int resumeSize = data["resumeSize"].asInt(); //resumeSize=140155 } InternetCloseHandle(hRequest); InternetCloseHandle(hConnect); InternetCloseHandle(hSession); if (code == 3002) //此候選人已存在(但簡歷不一樣),返回UI提示是替換,還是導入? { return 2; } if(code==0 || code==3000) return 1; //3000表示之前已上傳過完全相同的簡歷,算成功.(會返回候選人ID ) LOG_ERROR(L"-----上傳數據失敗,后台返回 code: %d,Msg:%s------", code, sss); return 0; }