VC编写自己构造http协议数据的post上传图片类(MFC环境 带编码转换)(转)

上次用VC写了个MFC环境下的post数据类,地址:

/Html/diannaojishu/2009-10/4905858580.html

这次将这个类进行扩展,可以post图片。但这两个post所使用的方法不一样。

post数据,是直接在http协议头将Content-Type设为application/x-www-form-urlencoded,这样 服务器会将提交的数据,当作表单数据处理。发送的数据格式也为:userid=lilu&data=post图片类&name=天漏客。 而post图片则是自己构造http协议数据,将http协议头的Content-Type设为multipart/form-data,同时还要加上 boundary=xxxxxxx(xxxxxxx表示一个字符串),后面的协议数据内容将要以这个xxxxxxx来进行分隔。发送的数据格式为:

---------------2389jhrwfjsjd9823
Content-Disposition: form-data; name="userid"

27EF272F28239E5A34EE223FADFWAFAEaE

类源码下载:点击浏览下一页[点击浏览该文件:SendData类源码.rar]

实例源码下载:点击浏览下一页[点击浏览该文件:UploadPhoto实例加源码.rar]

首先说一下本类的方便之处。

1、使用方便,步骤简单。
2、发送图片时,还可以构造其他数据。
3、兼容_MBCS和_UNICODE模式,并且能使用GB2312和UTF8两种编码进行发送与接收,类自动实现转换。

首先说一下这个类的使用,方法比较简单。

1、在工程中加入SendData.h和SendData.cpp文件,然后包含头文件,就可以定义类。

CSendData    MySend;

2、设置服务器参数。

 MySend.SetServerParam(_T(www.lilu.name),_T("/posttest.asp"),80);

3、如果同时要包含数据,就要先构造数据。

 MySend.MakePostData(_T("userid"),_T("lilu"));
 MySend.MakePostData(_T("name"),_T("天漏客"));
 MySend.MakePostData(_T("homepage"),_T(www.lilu.name));

4、发送图片。定义好接收数据的指针,以及发送和接收的编码。

 TCHAR  *pRecvData = NULL; //接收数据的指针
 DWORD  dwRecvSize = 0;  //接收数据的大小
 DWORD  dwRetSend = 0;  //发送函数返回值
 int   SendCode = HTTP_POST_GB2312,RecvCode =HTTP_POST_GB2312; //发送与接收的编码
 
dwRetSend = MySend.PostPicDataMethod(_T("c:\\pic\\测试图片.jpg"),_T("filename"),
  &pRecvData,dwRecvSize,
  SendCode,RecvCode);
 //处理接收数据,返回值。
 //99:图片不存在
 //100:正常成功
 //101:服务器无法连接
 //102:提交页面无法打开
 //103:数据发送失败
 //104:服务器处理失败
 //500:异常错误

5、处理结果

类自动的根据编译环境,将返回指针转换为LPTSTR类型,所以你只需要定义一个LPTSTR类型的指针,将其地址传递给发送函数即可。类会自己分 配内存存储返回的结果,并且会自动释放。所以使用时要注意,当这个类的作用域结束时,相应的接收数据内存也会释放掉,你可以将接收数据另拷贝一份,或者在 它的作用域内处理掉也可。

CString strRecv(pRecvData);    //将接收数据复制到strRecv中。

6、完毕。

测试一下啊!界面如下:

  1. 我本地IIS假设服务器,写入上传代码。然后使用软件提交,抓包如下:  
  2.   
  3. POST /upload.asp HTTP/1.1  
  4. Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/xaml+xml,*/* 
  5. Accept-Encoding: gzip, deflate 
  6. Accept-Language: zh-cn 
  7. Content-Type: multipart/form-data; boundary=-------------2389jhrwfjsjd9823 
  8. Cache-Control: no-cache 
  9. User-Agent: UploadPhoto 
  10. Host: 192.168.2.111 
  11. Content-Length: 39725 
  12.  
  13. ---------------2389jhrwfjsjd9823 
  14. Content-Disposition: form-data; name="Crypt" 
  15.  
  16. 10 
  17. ---------------2389jhrwfjsjd9823 
  18. Content-Disposition: form-data; name="type" 
  19.  
  20. 200 
  21. ---------------2389jhrwfjsjd9823 
  22. Content-Disposition: form-data; name="userid" 
  23.  
  24. 27EF272F28239E5A34EE223FADFWAFAEaE 
  25. ---------------2389jhrwfjsjd9823 
  26. Content-Disposition: form-data; name="filename"; filename="D:\Lilu.Other\QQ图片\软件工程图解.jpg" 
  27. Content-Type: image/pjpeg 
  28.  
  29. ……………………省略图片二进制数据……………… 
  30.  
  31. ---------------2389jhrwfjsjd9823 
  32. Content-Disposition: form-data; name="Submit" 
  33.  
  34. submit 
  35. ---------------2389jhrwfjsjd9823-- 
  36.  
  37. 这就是整个软件发送的数据,懂http协议的话,很容易理解这些数据。服务器返回: 
  38.  
  39. HTTP/1.1 200 OK 
  40. Server: Microsoft-IIS/5.1 
  41. Date: Wed, 04 Nov 2009 02:48:12 GMT 
  42. Content-Length: 171 
  43. Content-Type: text/html 
  44. Set-Cookie: ASPSESSIONIDSCRSBCRQ=ACBHPAHADINHKHIANAALFKOO; path=/ 
  45. Cache-control: private 
  46.  
  47.   
  48. <html>  
  49. <head>  
  50. <title>文件上传</title>  
  51. </head>  
  52. <body>  
  53. <font size=2>文件上传成功 [ <a href=# onclick=history.go(-1)>继续上传</a> ]</font>  
  54. </body>  
  55. </html>  
  56.  
  57.  最后贴一下这个类的源代码: 
  58.  
  59. ======================================================= 
  60. 首先是头文件:SendData.h 
  61.  
  62. // SendData.h: interface for the CSendData class. 
  63. // 
  64. ////////////////////////////////////////////////////////////////////// 
  65.  
  66. #if !defined(AFX_SENDDATA_H__F98D6FB7_D797_4947_A17E_13E88D20F35F__INCLUDED_) 
  67. #define AFX_SENDDATA_H__F98D6FB7_D797_4947_A17E_13E88D20F35F__INCLUDED_ 
  68.  
  69. #if _MSC_VER > 1000 
  70. #pragma once 
  71. #endif // _MSC_VER > 1000 
  72.  
  73. #include <afxinet.h> 
  74. #include <string> 
  75. using std::string; 
  76.  
  77. #define HTTP_POST_GB2312 1 //发送和接收的网页编码 
  78. #define HTTP_POST_UTF8  2 
  79.  
  80. class CSendData   
  81. { 
  82. public: 
  83.  CSendData(); 
  84.  virtual ~CSendData(); 
  85.  void SetServerParam(TCHAR ServerName[100],TCHAR ObjectName[100],WORD Port); 
  86.  //构造协议数据内容 
  87.  BOOL MakePostData(LPCTSTR pPostName, LPCTSTR pPostValue); 
  88.  BOOL MakePostData(LPCTSTR pPostName,int iPostValue); 
  89.  //发送带图片的数据 
  90.  DWORD PostPicDataMethod(TCHAR PicPath[MAX_PATH],LPCTSTR pPostName, 
  91.   LPTSTR *pRecvData, DWORD &RecvSize, 
  92.   int SendCode = HTTP_POST_GB2312,//发送和接收的编码 
  93.   int RecvCode = HTTP_POST_GB2312);  
  94.  //发送文本类数据 
  95.  DWORD PostDataMethod(LPCTSTR strDataSend, int DataSize,  
  96.   LPTSTR *pRecvData, DWORD &RecvSize, 
  97.   int SendCode = 1,int RecvCode = 1); 
  98. private: 
  99.  CString   m_strBoundary; //数据分隔符 
  100.  CString   m_strHeaderData; //协议头数据 
  101.  CString   m_strPostData; //协议正文数据 
  102.  CString   m_strEndData; //协议尾数据 
  103.  
  104.  void MakeHeaderData(); //构造协议头部数据 
  105.  void MakeEndData();  //构造协议尾部数据 
  106.  void MakePostPicData(LPCTSTR pPostName, LPCTSTR pPostValue); //构造图片前缀数据 
  107.  
  108.  //返回值为图片大小,返回值为0表示不存在。 
  109.  DWORD GetExistPic(TCHAR PicPath[MAX_PATH]); 
  110.  //服务器参数 
  111.  INTERNET_PORT m_nPort;  
  112.  TCHAR m_tzObjectName[100]; 
  113.  TCHAR m_tzServerName[100]; 
  114.  /////编码转换///////////////////////////////////////////////////////////// 
  115.  char * m_lpUTF8;   //UTF8编码缓存指针 
  116.  char * m_lpMultiByte; //Multil多字节编码指针 
  117.  wchar_t * m_wpWideChar;  //Widechar编码缓存指针 
  118.  int  m_nUTF8Len;  
  119.  int  m_nMultiByteLen; 
  120.  int  m_nWideCharLen; 
  121.   
  122.  void WideCharToUTF8(LPCWSTR wpWideData, int WideLen); 
  123.  void MultiByteToUTF8(LPCSTR lpMultiData, int MultiLen); 
  124.  void UTF8ToWideChar(LPCSTR pUTF8,int UTF8Len); 
  125.  void UTF8ToMultiByte(LPCSTR pUTF8, int UTF8Len); 
  126.  void MultiToWide(LPCSTR strDataSend, int DataSize); 
  127.  void MultiToMulti(LPCSTR strDataSend, int DataSize); 
  128.  void WideToMulti(LPCWSTR wpWideData, int WideLen); 
  129.  
  130. }; 
  131.  
  132. #endif // !defined(AFX_SENDDATA_H__F98D6FB7_D797_4947_A17E_13E88D20F35F__INCLUDED_) 
  133.  
  134.  
  135. ======================================================== 
  136. 接着是SendData.cpp文件。 
  137.  
  138. // UploadPhotoDlg.cpp : implementation file 
  139. // 
  140.  
  141. #include "stdafx.h" 
  142. #include "UploadPhoto.h" 
  143. #include "UploadPhotoDlg.h" 
  144.  
  145. #include "SendData.h" 
  146.  
  147. #ifdef _DEBUG 
  148. #define new DEBUG_NEW 
  149. #undef THIS_FILE 
  150. static char THIS_FILE[] = __FILE__; 
  151. #endif 
  152.  
  153. ///////////////////////////////////////////////////////////////////////////// 
  154. // CUploadPhotoDlg dialog 
  155.  
  156. CUploadPhotoDlg::CUploadPhotoDlg(CWnd* pParent /*=NULL*/)  
  157.  : CDialog(CUploadPhotoDlg::IDD, pParent)  
  158. {  
  159.  //{{AFX_DATA_INIT(CUploadPhotoDlg)   
  160.  m_strPhotoPath = _T("");  
  161.  m_nPort = 80;  
  162.  m_strRecvData = _T("");  
  163. //  m_strObjectName = _T("/frontend_dev.php/device/retriever");   
  164. //  m_strServerName = _T("trunk.xunhui1.net");   
  165.  m_strObjectName = _T("/upload.asp");  
  166.  m_strServerName = _T("192.168.2.111");  
  167.  m_PostName = _T("userid");  
  168.  m_PostValue = _T("27EF272F28239E5A34EE223FADFWAFAEaE");  
  169.  //}}AFX_DATA_INIT   
  170.  // Note that LoadIcon does not require a subsequent DestroyIcon in Win32   
  171.  m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);  
  172. }  
  173.   
  174. void CUploadPhotoDlg::DoDataExchange(CDataExchange* pDX)  
  175. {  
  176.  CDialog::DoDataExchange(pDX);  
  177.  //{{AFX_DATA_MAP(CUploadPhotoDlg)   
  178.  DDX_Text(pDX, IDC_EDIT_OBJECTNAME, m_strObjectName);  
  179.  DDX_Text(pDX, IDC_EDIT_PHOTOPATH, m_strPhotoPath);  
  180.  DDX_Text(pDX, IDC_EDIT_PORT, m_nPort);  
  181.  DDX_Text(pDX, IDC_EDIT_RECVDATA, m_strRecvData);  
  182.  DDX_Text(pDX, IDC_EDIT_SERVERNAME, m_strServerName);  
  183.  DDX_Text(pDX, IDC_EDIT_POSTDATANAME, m_PostName);  
  184.  DDX_Text(pDX, IDC_EDIT_POSTDATAVALUE, m_PostValue);  
  185.  //}}AFX_DATA_MAP   
  186. }  
  187.   
  188. BEGIN_MESSAGE_MAP(CUploadPhotoDlg, CDialog)  
  189.  //{{AFX_MSG_MAP(CUploadPhotoDlg)   
  190.  ON_WM_PAINT()  
  191.  ON_WM_QUERYDRAGICON()  
  192.  ON_BN_CLICKED(IDC_BTN_SEND, OnBtnSend)  
  193.  ON_BN_CLICKED(IDC_BTN_FILEOPEN, OnBtnFileopen)  
  194.  //}}AFX_MSG_MAP   
  195. END_MESSAGE_MAP()  
  196.   
  197. /////////////////////////////////////////////////////////////////////////////   
  198. // CUploadPhotoDlg message handlers   
  199.   
  200. BOOL CUploadPhotoDlg::OnInitDialog()  
  201. {  
  202.  CDialog::OnInitDialog();  
  203.   
  204.  // Set the icon for this dialog.  The framework does this automatically   
  205.  //  when the application's main window is not a dialog   
  206.  SetIcon(m_hIcon, TRUE);   // Set big icon   
  207.  SetIcon(m_hIcon, FALSE);  // Set small icon   
  208.    
  209.  // TODO: Add extra initialization here   
  210.  ((CButton*)GetDlgItem(IDC_RADIO_SENDGB2312))->SetCheck(TRUE);  
  211.  ((CButton*)GetDlgItem(IDC_RADIO_RECVGB2312))->SetCheck(TRUE);  
  212.   
  213.  return TRUE;  // return TRUE  unless you set the focus to a control   
  214. }  
  215.   
  216. // If you add a minimize button to your dialog, you will need the code below   
  217. //  to draw the icon.  For MFC applications using the document/view model,   
  218. //  this is automatically done for you by the framework.   
  219.   
  220. void CUploadPhotoDlg::OnPaint()   
  221. {  
  222.  if (IsIconic())  
  223.  {  
  224.   CPaintDC dc(this); // device context for painting   
  225.   
  226.   SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);  
  227.   
  228.   // Center icon in client rectangle   
  229.   int cxIcon = GetSystemMetrics(SM_CXICON);  
  230.   int cyIcon = GetSystemMetrics(SM_CYICON);  
  231.   CRect rect;  
  232.   GetClientRect(&rect);  
  233.   int x = (rect.Width() - cxIcon + 1) / 2;  
  234.   int y = (rect.Height() - cyIcon + 1) / 2;  
  235.   
  236.   // Draw the icon   
  237.   dc.DrawIcon(x, y, m_hIcon);  
  238.  }  
  239.  else  
  240.  {  
  241.   CDialog::OnPaint();  
  242.  }  
  243. }  
  244.   
  245. // The system calls this to obtain the cursor to display while the user drags   
  246. //  the minimized window.   
  247. HCURSOR CUploadPhotoDlg::OnQueryDragIcon()  
  248. {  
  249.  return (HCURSOR) m_hIcon;  
  250. }  
  251.   
  252. void CUploadPhotoDlg::OnBtnSend()   
  253. {  
  254.  // TODO: Add your control notification handler code here   
  255.  GetDlgItem(IDC_BTN_SEND)->EnableWindow(FALSE);  
  256.    
  257.  UpdateData(TRUE);  
  258.  //定义发送类   
  259.  CSendData MySend;   
  260.  TCHAR  *pRecvData = NULL; //接收数据的指针   
  261.  DWORD  dwRecvSize = 0;  //接收数据的大小   
  262.  DWORD  dwRetSend = 0;  //发送函数返回值   
  263.  int   SendCode = HTTP_POST_GB2312,RecvCode =HTTP_POST_GB2312; //发送与接收的编码   
  264.  //设置服务器参数   
  265.  MySend.SetServerParam((LPTSTR)(LPCTSTR)m_strServerName,(LPTSTR)(LPCTSTR)m_strObjectName,m_nPort);  
  266.   
  267.  //确定发送方法   
  268.  if (1 == ((CButton*)GetDlgItem(IDC_RADIO_SENDGB2312))->GetCheck())  
  269.  {  
  270.   SendCode = HTTP_POST_GB2312;  
  271.  }  
  272.  else  
  273.  {  
  274.   SendCode = HTTP_POST_UTF8;  
  275.  }  
  276.  //确定接收编码   
  277.  if (1 == ((CButton*)GetDlgItem(IDC_RADIO_RECVGB2312))->GetCheck())  
  278.  {  
  279.   RecvCode = HTTP_POST_GB2312;   
  280.  }  
  281.  else  
  282.  {  
  283.   RecvCode = HTTP_POST_UTF8;  
  284.  }  
  285.  //必须先构造数据包   
  286.  MySend.MakePostData(_T("Crypt"),_T("10"));  
  287.  MySend.MakePostData(_T("type"),_T("200"));  
  288.  MySend.MakePostData(m_PostName,m_PostValue);  
  289.  //发送   
  290.  dwRetSend = MySend.PostPicDataMethod((LPTSTR)(LPCTSTR)m_strPhotoPath,_T("filename"),  
  291.   &pRecvData,dwRecvSize,  
  292.   SendCode,RecvCode);  
  293.  //处理接收数据   
  294.  //99:图片不存在   
  295.  //100:正常成功   
  296.  //101:服务器无法连接   
  297.  //102:提交页面无法打开   
  298.  //103:数据发送失败   
  299.  //104:服务器处理失败   
  300.  //500:异常错误   
  301.  if (dwRetSend == 100)  
  302.  {  
  303.   MessageBox(_T("发送成功"));  
  304.  }  
  305.  else if (dwRetSend == 99 )  
  306.  {  
  307.   MessageBox(_T("发送成功"));  
  308.  }  
  309.  else if (dwRetSend == 101 )  
  310.  {  
  311.   MessageBox(_T("服务器无法连接"));  
  312.  }  
  313.  else if (dwRetSend == 102 )  
  314.  {  
  315.   MessageBox(_T("提交页面无法打开"));  
  316.  }  
  317.  else if (dwRetSend == 103 )  
  318.  {  
  319.   MessageBox(_T("数据发送失败"));  
  320.  }  
  321.  else if (dwRetSend == 104 )  
  322.  {  
  323.   MessageBox(_T("服务器处理失败"));  
  324.  }  
  325.  else if (dwRetSend == 500 )  
  326.  {  
  327.   MessageBox(_T("异常错误"));  
  328.  }  
  329.  //更新返回数据框   
  330.  m_strRecvData = pRecvData;  
  331.  UpdateData(FALSE);  
  332.     
  333.  GetDlgItem(IDC_BTN_SEND)->EnableWindow(TRUE);  
  334.   
  335. }  
  336.   
  337. void CUploadPhotoDlg::OnBtnFileopen()   
  338. {  
  339.  // TODO: Add your control notification handler code here   
  340.  TCHAR tzFilter[] = _T("jpg图片(*.jpg;*.jpeg)|*.jpg;*.jpeg|gif图片(*.gif)|*.gif|所有文件(*.*)|*.*||");  
  341.  CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_ENABLESIZING|OFN_EXPLORER,  
  342.   tzFilter,NULL);  
  343.  if (dlg.DoModal() == IDOK)  
  344.  {  
  345.   m_strPhotoPath = dlg.GetPathName();  
  346.   UpdateData(FALSE);  
  347.  }  
  348.   
posted @ 2012-11-16 11:25  郑文亮  阅读(979)  评论(1编辑  收藏  举报