HTTP上传数据 :表单,二进制数据(multipart/form-data application/octet-stream boundary)

时间:2024-09-13 00:07:02

使用WinINet

一个较简单的例子:上传头像

void CBackstageManager::UpdateAvatarThreadProc(LPVOID params)
{
stForThread* pSt = (stForThread* )params; HINTERNET hSession=;
HINTERNET hConnect=;
HINTERNET hRequest=; DWORD dwNumberOfBytesWritten=;
DWORD dwBytesSend=;
DWORD dwFlag = ; hSession=InternetOpen(_T("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0"),
INTERNET_OPEN_TYPE_PRECONFIG, , INTERNET_INVALID_PORT_NUMBER, );
if (==hSession)
{
SAFE_DELETE(pSt);
NotifyManager::Instance().Notify(TaskListener::TASK_TYPE_UPDATE_AVATAR_RESULT, TaskListener::TASK_STATUS_TIMEOUT,);
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, , ); //URL_HOST不能带http://
if (==hConnect)
{
SAFE_DELETE(pSt);
NotifyManager::Instance().Notify(TaskListener::TASK_TYPE_UPDATE_AVATAR_RESULT, TaskListener::TASK_STATUS_TIMEOUT,);
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,
, //Referrer
, //AcceptTypes
dwFlag,
);
if (==hRequest)
{
InternetCloseHandle(hConnect);
InternetCloseHandle(hSession);
SAFE_DELETE(pSt);
NotifyManager::Instance().Notify(TaskListener::TASK_TYPE_UPDATE_AVATAR_RESULT, TaskListener::TASK_STATUS_TIMEOUT,);
return ;
} //设置Header
CString content_type = TEXT("Content-Type: multipart/form-data; boundary=");
content_type.Append(_T(ABOUNDARY));
HttpAddRequestHeaders(hRequest,content_type,-,HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE); //验证cid和token
CString szAuthorization = TEXT("Authorization: ");
szAuthorization.Append(CBackstageManager::GetInstance().GetAuthorizationString());
HttpAddRequestHeaders(hRequest,szAuthorization, -,HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);
szAuthorization = TEXT("Agent-Info: ");
szAuthorization.Append(CBackstageManager::GetInstance().GetAgentInfo());
HttpAddRequestHeaders(hRequest,szAuthorization, -,HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE); //读取文件内容和长度
HANDLE hFile;
hFile=CreateFile(pSt->sTmp, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, ,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, );
DWORD dwFileSize=GetFileSize(hFile,);
BYTE* lpBuffer=(BYTE*)VirtualAlloc(,dwFileSize,MEM_COMMIT,PAGE_READWRITE);
if (==lpBuffer)
{
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hSession);
SAFE_DELETE(pSt);
NotifyManager::Instance().Notify(TaskListener::TASK_TYPE_UPDATE_AVATAR_RESULT, TaskListener::TASK_STATUS_ERROR,);
return ;
}
DWORD dwRead;
ReadFile(hFile,lpBuffer,dwFileSize,&dwRead,);
CloseHandle(hFile); char first_boundary[]={};
char delimiter[]={};
char end_boundary[]={};
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[]={};
int length = strlen(first_boundary); CString stmName = PathFindFileName(pSt->sTmp);
char content_dispos2[]={};
if(stmName.GetLength() > )
{
stmName = stmName.Left() + 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 = ;
BufferIn.dwHeadersTotal = ;
BufferIn.lpvBuffer = NULL;
BufferIn.dwBufferLength = ;
BufferIn.dwBufferTotal = length;
BufferIn.dwOffsetLow = ;
BufferIn.dwOffsetHigh = ; if (!HttpSendRequestEx(hRequest,&BufferIn,,,))
{
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,);
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,,,))
HttpEndRequest(hRequest,,,); VirtualFree(lpBuffer,,MEM_RELEASE); //获取返回数据
std::stringstream sstream;
CParseResumeTask::GetResponse(&sstream, hRequest, );
Json::Value root;
Json::Reader reader;
reader.parse(sstream.str(), root);
int code = -;
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 == )
{
{
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,);
}
else
{
if (code == || code == )
CBackstageManager::NotifyUnlogged(code == );
else
NotifyManager::Instance().Notify(TaskListener::TASK_TYPE_UPDATE_AVATAR_RESULT, TaskListener::TASK_STATUS_ERROR,);
} SAFE_DELETE(pSt);
}

较麻烦的实例:上传简历文件,及各项参数

int CParseResumeTask::UpdateToServer2(const stResumeInfo& st, int& candId, CString& szUpdateTime, int& nFileSize, int& reposedCode)
{
HINTERNET hSession=;
HINTERNET hConnect=;
HINTERNET hRequest=; DWORD dwNumberOfBytesWritten=;
DWORD dwBytesSend=;
DWORD dwFlag = ;
reposedCode = ; candId = ;
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, , INTERNET_INVALID_PORT_NUMBER, );
if (==hSession)
{
reposedCode = -;
return ;
} unsigned short port_ = INTERNET_DEFAULT_HTTP_PORT;
if (CConfig::GetServerType() == ) //外网用HTTPS
{
port_ = INTERNET_DEFAULT_HTTPS_PORT;
}
hConnect=InternetConnect(hSession, CConfig::URL_HOST, port_, _T(""), _T(""), INTERNET_SERVICE_HTTP, , ); //URL_HOST不能带http://
if (==hConnect)
{
InternetCloseHandle(hSession);
reposedCode = -;
return ;
} dwFlag=INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_AUTH | INTERNET_FLAG_NO_UI ;
if (CConfig::GetServerType() == ) //外网用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, , , dwFlag, );//old
#else
hRequest=HttpOpenRequest(hConnect, _T("POST"), RESUME_UPLOAD_URL_NEW, HTTP_VERSION, , , dwFlag, );
#endif
if (==hRequest)
{
InternetCloseHandle(hConnect);
InternetCloseHandle(hSession);
reposedCode = -;
return ;
} if (m_bCancel) return ; //设置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,-,HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE); //如果当前用户ID与预存的用户ID不一致(已登出,或已登录新账户),不再上传
int userid = CBackstageManager::GetInstance().GetUserId();
if (m_nCurUserid != userid)
return ; //验证cid和token
CString szAuthorization = TEXT("Authorization: ");
szAuthorization.Append(/*CA2T(s64, CP_UTF8)*/CBackstageManager::GetInstance().GetAuthorizationString());
HttpAddRequestHeaders(hRequest,szAuthorization, -,HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);
szAuthorization = TEXT("Agent-Info: ");
szAuthorization.Append(CBackstageManager::GetInstance().GetAgentInfo());
HttpAddRequestHeaders(hRequest,szAuthorization, -,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, ,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, );
DWORD dwFileSize=GetFileSize(hFile,);
BYTE* lpBuffer=(BYTE*)VirtualAlloc(,dwFileSize,MEM_COMMIT,PAGE_READWRITE);
if (==lpBuffer)
{
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hSession);
LOG_INFO(L"----- updateResume VirtualAlloc return 0 !!! GetLastError: %d------", GetLastError());
return ;
}
DWORD dwRead;
ReadFile(hFile,lpBuffer,dwFileSize,&dwRead,);
CloseHandle(hFile);
#endif char first_boundary[]={};
char delimiter[]={};
char end_boundary[]={};
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[]={};
std::map<std::string, std::string>::iterator it = ssmap.begin();
int length = strlen(first_boundary);
for(; it != ssmap.end(); it++)
{
memset(content_dispos, , 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[]={};
CString stmName = st.file_name;
if(stmName.GetLength() > )
{
stmName = stmName.Left() + 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 = ;
BufferIn.dwHeadersTotal = ;
BufferIn.lpvBuffer = NULL;
BufferIn.dwBufferLength = ;
BufferIn.dwBufferTotal = length;
BufferIn.dwOffsetLow = ;
BufferIn.dwOffsetHigh = ; if (!HttpSendRequestEx(hRequest,&BufferIn,,,))
{
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hSession);
reposedCode = -;
return ;
} //上传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 = ; iter != ssmap.end(); iter++, index++)
{
memset(content_dispos, , 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-))
#endif
InternetWriteFile(hRequest,(byte*)delimiter,strlen(delimiter),&dwNumberOfBytesWritten);
} if (m_bCancel) return ; #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,,,))
{
int a = GetLastError();
HttpEndRequest(hRequest,,,);
} #ifdef UP_FILE_TO_SEVER
VirtualFree(lpBuffer,,MEM_RELEASE);
#endif
if (m_bCancel) return ;
//获取返回数据
std::stringstream sstream;
GetResponse(&sstream, hRequest, );
Json::Value root;
Json::Reader reader;
reader.parse(sstream.str(), root);
int code = -;
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 == ) //此候选人已存在(但简历不一样),返回UI提示是替换,还是导入?
{
return ;
} if(code== || code==)
return ; //3000表示之前已上传过完全相同的简历,算成功.(会返回候选人ID ) LOG_ERROR(L"-----上传数据失败,后台返回 code: %d,Msg:%s------", code, sss);
return ;
}