欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

WinInet模拟HTTP POST上传二进制文件流

程序员文章站 2022-05-16 15:49:38
...
BOOL CDllValidateDlg::PostHttpPage(CString &result,CString &PageName,CString &postData) // 请求Http.{	CInternetSession session("SighAgent");	try	{		INTERNET_PORT nPort = 80;		DWORD dwRet = 0;		/*以下为wininet 网络请求流程*/		CHttpConnection* pServer = session.GetHttpConnection(SERVER_IP, nPort);		CHttpFile* pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_POST,PageName); //打开一个请求		CString strHeaders = "Content-Type: application/x-www-form-urlencoded"; // 请求头		//开始发送请求				string data_post = MultiByteToUtf8(postData.GetBuffer(0));		pFile->SendRequest(strHeaders,(LPVOID)data_post.data(),data_post.size()); //发送请求,注意此为堵塞函数		pFile->QueryInfoStatusCode(dwRet); //发送请求后,就查询发送的结果		if (dwRet == HTTP_STATUS_OK) //这个代表请求正确		{			CString str;			while(pFile->ReadString(str)) //开始返回返回结果 			{				char *pStr = (char*)str.GetBuffer(str.GetLength()); //取得str对象的原始字符串 				result = result + str; 			}			result = Utf8ToMultiByte(result.GetBuffer(0)).c_str();		}		else		{			SAFE_DELETE(pFile);			SAFE_DELETE(pServer);			return FALSE;		}		SAFE_DELETE(pFile);		SAFE_DELETE(pServer);	}	catch (CInternetException* pEx)	{		//catch errors from WinInet		TCHAR pszError[200];		pEx->GetErrorMessage(pszError, 200);		OutputDebugString(pszError);		return FALSE;	}	session.Close();	return TRUE;}

我在程序里用到上面这个PostHttpPage函数,来和服务器交互数据。
之前的一些数据上传都是字符串或整型数,没出现过问题。
现在想用这同一个函数,上传二进制形式的文件流,没有成功。请问我下面的做法是哪里错了?
//二进制导入图片文件	char buffer[102400];  //BUF_SIZE大小自己定义	FILE * pFile = fopen("photo.bmp", "rb");	int img = fread(buffer, sizeof(char), 102400, pFile);//	char stzimg[100];//	itoa(img,stzimg,10);//	AfxMessageBox(stzimg);//二进制导入图片文件结束	CString post_data;	post_data.Format("matchid='%s'&matchname='%s'&aid='%d'&ticket='%d'"		"&name='%s'&gender='%d'&folk='%s'&birthday='%s'&addr='%s'&cardid='%s'&expire='%s'&agency='%s'&face='%s'",		matchID,matchName,AID,ticket,		Name,abs(stricmp(Gender,"女")),Folk,BirthDay,Address,Code, ExpireEnd,   Agency,buffer); //请求的附加参数	CString result; //返回的结果	CString post_page = "test_id_validater/update_num.php"; //请求的php	PostHttpPage(result,post_page,post_data);


回复讨论(解决方案)

二进制考虑用BASE64编码等,然后Post

你确定html协议是这样传二进制文件的吗,先用wireshark查看下

我在网上找到上传文件的代码是这个样子的:

  #include   #include   #include   #define ERROR_OPEN_FILE       10  #define ERROR_MEMORY          11  #define ERROR_SIZE            12  #define ERROR_INTERNET_OPEN   13  #define ERROR_INTERNET_CONN   14  #define ERROR_INTERNET_REQ    15  #define ERROR_INTERNET_SEND   16  using namespace std;  int main()  {     // Local variables     static char *filename   = "test.txt";   //Filename to be loaded     static char *type       = "image/jpg";     static char boundary[]  = "pippo";            //Header boundary     static char nameForm[]  = "uploadedfile";     //Input form name     static char iaddr[]     = "localhost";        //IP address     static char url[]       = "test.php";         //URL     char hdrs[255];                  //Headers     char * buffer;                   //Buffer containing file + headers     char * content;                  //Buffer containing file     FILE * pFile;                    //File pointer     long lSize;                      //File size     size_t result;                        // Open file     pFile = fopen ( filename , "rb" );     if (pFile==NULL) return ERROR_OPEN_FILE;     // obtain file size:     fseek (pFile , 0 , SEEK_END);     lSize = ftell (pFile);     rewind (pFile);     // allocate memory to contain the whole file:     content = (char*) malloc (sizeof(char)*lSize);     if (content == NULL) return ERROR_MEMORY;     // copy the file into the buffer:     result = fread (content,1,lSize,pFile);     if (result != lSize) return ERROR_SIZE;     // terminate     fclose (pFile);     //allocate memory to contain the whole file + HEADER     buffer = (char*) malloc (sizeof(char)*lSize + 2048);     //print header     sprintf(hdrs,"Content-Type: multipart/form-data; boundary=%s",boundary);     sprintf(buffer,"--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n",boundary,nameForm,filename);     sprintf(buffer,"%sContent-Type: %s\r\n\r\n",buffer,type);     sprintf(buffer,"%s%s\r\n",buffer,content);     sprintf(buffer,"%s--%s--\r\n",buffer,boundary);     //Open internet connection     HINTERNET hSession = InternetOpen("WinSock",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);     if(hSession==NULL) return ERROR_INTERNET_OPEN;     HINTERNET hConnect = InternetConnect(hSession, iaddr,INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);     if(hConnect==NULL) return ERROR_INTERNET_CONN;     HINTERNET hRequest = HttpOpenRequest(hConnect, (const char*)"POST",url, NULL, NULL, (const char**)"*/*\0", 0, 1);     if(hRequest==NULL) return ERROR_INTERNET_REQ;     BOOL sent= HttpSendRequest(hRequest, hdrs, strlen(hdrs), buffer, strlen(buffer));     if(!sent) return ERROR_INTERNET_SEND;     //close any valid internet-handles     InternetCloseHandle(hSession);     InternetCloseHandle(hConnect);     InternetCloseHandle(hRequest);     return 0;  }

这应该是把文件以二进制形式传给test.php吧。那么在test.php那边怎么接收这个二进制,并写入mysql数据库的某个字段呢?

它可以和别的整型数及字串在同一次post中提交吗?

这应该是把文件以二进制形式传给test.php吧。那么在test.php那边怎么接收这个二进制,并写入mysql数据库的某个字段呢?


要看对应的php是如何处理的。然后你发送对应格式的数据


这应该是把文件以二进制形式传给test.php吧。那么在test.php那边怎么接收这个二进制,并写入mysql数据库的某个字段呢?


要看对应的php是如何处理的。然后你发送对应格式的数据

对应PHP文件是用$bian_liang_ming = $_REQUEST['xxxx'];
来获取传过去的参数的。这种情况如何传递二进制数据流啊?

你是玩C的,你应该清楚的知道字符串是依靠尾部附加的 '\0' 来判断结束的,那你如何能保证图片数据中不出现'\0' 而导致字符串提前结束呢?

你是玩C的,你应该清楚的知道字符串是依靠尾部附加的 '\0' 来判断结束的,那你如何能保证图片数据中不出现'\0' 而导致字符串提前结束呢?


我其实并不知道确切该怎么做,所以随便套用了之前传递整型数的办法,知道是不对的。

c++ 应用 curl 库函数实现,这样少了协议的处理,事情变得单纯了
也可以用 sock 库函数实现
你 #3 的代码就是 sock 应用的一个例子