使用Http协议Post上传文件

使用Http协议Post上传文件

2023年6月25日发(作者:)

使⽤Http协议Post上传⽂件转载:h1.使⽤场景 公司产品需要做⼀个关于收集程序崩溃信息的模块(BugReport),需要客户端程序在崩溃发⽣后将崩溃⽇志以及转储⽂件发送到后台。 格式  multipart/form-data 这⼜是⼀个常见的 POST 数据提交的⽅式。我们使⽤表单上传⽂件时,必须让

表单的enctype 等于 multipart/form-data。直接来看⼀个请求⽰例:BASHPOST HTTP/1.1Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA------WebKitFormBoundaryrGKCBY7qhFd3TrwAContent-Disposition: form-data; name="text" name:key两个空⾏ rnrntitle value:title------WebKitFormBoundaryrGKCBY7qhFd3TrwAContent-Disposition: form-data; name="file"; filename=""Content-Type: image/pngPNG ... content of ...------WebKitFormBoundaryrGKCBY7qhFd3TrwA--这个例⼦稍微复杂点。⾸先⽣成了⼀个 boundary ⽤于分割不同的字段,为了避免与正⽂内容重复,boundary 很长很复杂。然后 Content-Type ⾥指明了数据是以 multipart/form-data 来编码,本次请求的 boundary 是什么内容。消息主体⾥按照字段个数⼜分为多个结构类似的部分,每部分都是以

--boundary 开始,紧接着是内容描述信息,然后是回车,最后是字段具体内容(⽂本或⼆进制)。如果传输的是⽂件,还要包含⽂件名和⽂件类型信息。消息主体最后以

--boundary-- 标⽰结束。关于 multipart/form-data 的详细定义,请前往 查看。这种⽅式⼀般⽤来上传⽂件,各⼤服务端语⾔对它也有着良好的⽀持。上⾯提到的这两种 POST 数据的⽅式,都是浏览器原⽣⽀持的,⽽且现阶段标准中原⽣ 表单也(通过 元素的

enctype 属性指定,默认为

application/x-www-form-urlencoded。其实

enctype 还⽀持

text/plain,不过⽤得⾮常少)。随着越来越多的 Web 站点,尤其是 WebApp,全部使⽤ Ajax 进⾏数据交互之后,我们完全可以定义新的数据提交⽅式,给开发带来更多便利。

MFC代码:#include #include #include #include #include #include #include using namespace std;#pragma warning(disable : 4996)wstring Utf8ToUnicode(const char* szU8){ if (szU8 == NULL) return L""; if (strlen(szU8) == 0) return L""; //预转换,得到所需空间的⼤⼩; int wcsLen = ::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), NULL, 0); //分配空间要给'0'留个空间,MultiByteToWideChar不会给'0'空间 wchar_t* wszString = new wchar_t[wcsLen + 1]; //转换 ::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), wszString, wcsLen); //最后加上'0' wszString[wcsLen] = '0'; wstring unicodeString = wszString; delete[] wszString; wszString = NULL; return unicodeString;}string UnicodeToASNI(const wchar_t* unicode){ if (unicode == NULL) return ""; if (wcslen(unicode) == 0) return ""; int len; len = WideCharToMultiByte(CP_ACP, 0, unicode, -1, NULL, 0, NULL, NULL); char* szUtf8 = (char*)malloc(len + 1); memset(szUtf8, 0, len + 1); WideCharToMultiByte(CP_ACP, 0, unicode, -1, szUtf8, len, NULL, NULL); string sRet = szUtf8; free(szUtf8); szUtf8 = NULL; return sRet;}//ANSI ---> Unicodestd::wstring ANSIToUnicode(const string& str){ int Length = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0); if (Length == 0) return NULL; wchar_t * pUnicode = new wchar_t[Length + 1]; memset(pUnicode, 0, (Length + 1) * sizeof(wchar_t)); ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, (LPWSTR)pUnicode, Length); pUnicode[Length] = 0; wstring wstr = (wchar_t*)pUnicode; delete[] pUnicode; pUnicode = NULL; return wstr;}string UnicodeToUtf8(const wstring& wstr){ // 预算-缓冲区中多字节的长度

int ansiiLen = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr); // 给指向缓冲区的指针变量分配内存

char *pAssii = (char*)malloc(sizeof(char)*ansiiLen); // 开始向缓冲区转换字节

WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, pAssii, ansiiLen, nullptr, nullptr); string ret_str = pAssii; free(pAssii); return ret_str;}BOOL CSRCMBugReportDlg::UploadHttpFile(const CString& strUploadFileURL, const CString & strCrashFilePath, bool isHttps){ ASSERT(strUploadFileURL != ""); ASSERT(strCrashFilePath != ""); CInternetSession session(L"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36", 0); CHttpConnection* pHttpConnection = NULL; CHttpFile* pHttpFile = NULL; try { DWORD ServerType = 0; CString strServer, strObject; INTERNET_PORT wPort; CFile file; if (AfxParseURL(strUploadFileURL, ServerType, strServer, strObject, wPort)) { //打开本地待上传⽂件 if (!(strCrashFilePath, CFile::modeRead | CFile::shareDenyWrite | CFile::typeBinary))//如果⽂件路径有中⽂必须⽤ANSIToUnicode转成宽字节 { CString errText; (L"打开本地⽂件%s失败", strCrashFilePath); rror(errText); ::PostMessage(this->GetSafeHwnd(), WM_EXIT_BUGREPORT, 0, 0);//完成退出BugReport return FALSE; } const int nTimeOut = 5000;//5秒超时 ion(INTERNET_OPTION_CONNECT_TIMEOUT, nTimeOut); //重试之间的等待延时 ion(INTERNET_OPTION_CONNECT_RETRIES, 1); //重试1次数 if (isHttps) { pHttpConnection = pConnection(strServer, INTERNET_FLAG_SECURE, wPort, NULL, NULL); //连接Https服务器 } else { pHttpConnection = pConnection(strServer, wPort); //取得⼀个Http联接 } if (pHttpConnection) { if(isHttps) { pHttpFile = pHttpConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST,strObject,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 );//打开请求 ,这⼏个标识都要加上 } else { pHttpFile = pHttpConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST, strObject); } if (pHttpFile) { /*szBoundary,任意的⼀个串,⽤以标识body中的数据*/ //该串需要够复杂,⽤以区别当前请求包中的数据 const char * szBoundary = "----------------------------961038114493"; /*构造头部*/ pHttpFile->AddRequestHeaders(L"Accept:*/*"); pHttpFile->AddRequestHeaders(L"Accept-Encoding:gzip, deflate"); //构造头中的Content-Type项,其中需要填上boundary CString szContentType = L"Content-Type:multipart/form-data; boundary="; szContentType += szBoundary; pHttpFile->AddRequestHeaders(fer(0)); /*打开⽂件,合成⽂件头部数据,取出⽂件数据,以及合成尾部数据,计算总长度*/ struct DataInfo{ char* pBuf; DWORD BufLen; DataInfo(){ ZeroMemory(this, sizeof(DataInfo)); } }; std::vector DataInfoList; wstring strAccount = L"test@"; wstring strMsg = L"崩溃了"; CString FileName = eName(); char key1[1024] = { 0 }; sprintf(key1, "rn------------------------------961038114493rn" "Content-Disposition: form-data;name="Account" rnrn%s", UnicodeToUtf8(strAccount).c_str());//如果value有中⽂必须转成UTF-8 char key2[1024] = { 0 }; sprintf(key2, "rn------------------------------961038114493rn" "Content-Disposition: form-data;name="Message" rnrn%s", UnicodeToUtf8(strMsg).c_str());//如果value有中⽂必须转成UTF-8 char strFileconnet[1024]= { 0 }; sprintf(strFileconnet, "rn------------------------------961038114493rn" "Content-Disposition:form-data;name="file";filename="%"rn" "Content-Type:application/ziprnrn", UnicodeToUtf8(FileName).c_str()); //拼body string strconnet = key1; strconnet += key2; strconnet += strFileconnet; DWORD dwTotalBodyLen = 0; //每个⽂件的头部信息 DataInfo preDi; = strlen(strconnet.c_str()); = new char[]; memcpy(, strconnet.c_str(), ); _back(preDi); dwTotalBodyLen += ; //⽂件内容 DataInfo ContDi; = (DWORD)gth(); = new char[]; (, ); _back(ContDi); (); dwTotalBodyLen += ; //尾长度 const char* szEndContent = "rn" "------------------------------961038114493--rn"; DataInfo EndDi; = strlen(szEndContent); = new char[]; memcpy(, szEndContent, ); _back(EndDi); dwTotalBodyLen += ; /*发送数据*/ pHttpFile->SendRequestEx(dwTotalBodyLen, HSR_SYNC | HSR_INITIATE); std::vector::iterator it3 = (); for (; it3 != (); it3++) { pHttpFile->Write(it3->pBuf, it3->BufLen); delete[]it3->pBuf; } pHttpFile->EndRequest(HSR_SYNC); /*获取状态*/ char* RetStr = NULL; DWORD dwStatusCode = -1; pHttpFile->QueryInfoStatusCode(dwStatusCode); if (dwStatusCode == HTTP_STATUS_OK) { //读返回 RetStr = new char[(DWORD)pHttpFile->GetLength()]; pHttpFile->Read(RetStr, (UINT)pHttpFile->GetLength()); if (pHttpFile) delete pHttpFile; if (pHttpConnection) delete pHttpConnection; (); ::PostMessage(this->GetSafeHwnd(), WM_EXIT_BUGREPORT, 0, 0);//完成退出BugReport return TRUE; } else { if (pHttpFile != NULL) { pHttpFile->Close(); delete pHttpFile; pHttpFile = NULL; } if (pHttpConnection != NULL) { pHttpConnection->Close(); delete pHttpConnection; pHttpConnection = NULL; } (); CString errText; (L"POST出错,错误码:%d", dwStatusCode); rror(errText); ::PostMessage(this->GetSafeHwnd(), WM_EXIT_BUGREPORT, 0, 0);//完成退出BugReport return FALSE; } } } } } catch (...) { if (pHttpFile != NULL) { pHttpFile->Close(); delete pHttpFile; pHttpFile = NULL; } if (pHttpConnection != NULL) { pHttpConnection->Close(); delete pHttpConnection; pHttpConnection = NULL; } (); DWORD dwError = GetLastError(); CString str; (L"Unknow Exception occur %d", dwError); rror(str); ::PostMessage(this->GetSafeHwnd(), WM_EXIT_BUGREPORT, 0, 0);//完成退出BugReport return FALSE; } if (pHttpFile != NULL) pHttpFile->Close(); if (pHttpConnection != NULL) pHttpConnection->Close(); (); ::PostMessage(this->GetSafeHwnd(), WM_EXIT_BUGREPORT, 0, 0);//完成退出BugReport return TRUE;}int main(){ wstring url = L"localhost:8080"; wstring strFilepath; //获取⼯作路径 TCHAR szModulePath[MAX_PATH * 2] = { 0 }; ::GetModuleFileName(NULL, szModulePath, _countof(szModulePath) - 2); PathRemoveFileSpec(szModulePath); strFilepath = szModulePath; strFilepath += L"测试.zip"; PostUploadFile(url.c_str(), strFilepath .c_str()); return 0;} 点击下载:

发布者:admin,转转请注明出处:http://www.yc00.com/web/1687679490a30946.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信