zoukankan      html  css  js  c++  java
  • 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、完毕。

    测试一下啊!界面如下:

    点击浏览下一页

    我本地IIS假设服务器,写入上传代码。然后使用软件提交,抓包如下:

    POST /upload.asp HTTP/1.1
    Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/xaml+xml,*/*
    Accept-Encoding: gzip, deflate
    Accept-Language: zh-cn
    Content-Type: multipart/form-data; boundary=-------------2389jhrwfjsjd9823
    Cache-Control: no-cache
    User-Agent: UploadPhoto
    Host: 192.168.2.111
    Content-Length: 39725

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

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

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

    27EF272F28239E5A34EE223FADFWAFAEaE
    ---------------2389jhrwfjsjd9823
    Content-Disposition: form-data; name="filename"; filename="D:\Lilu.Other\QQ图片\软件工程图解.jpg"
    Content-Type: image/pjpeg

    ……………………省略图片二进制数据………………

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

    submit
    ---------------2389jhrwfjsjd9823--

    这就是整个软件发送的数据,懂http协议的话,很容易理解这些数据。服务器返回:

    HTTP/1.1 200 OK
    Server: Microsoft-IIS/5.1
    Date: Wed, 04 Nov 2009 02:48:12 GMT
    Content-Length: 171
    Content-Type: text/html
    Set-Cookie: ASPSESSIONIDSCRSBCRQ=ACBHPAHADINHKHIANAALFKOO; path=/
    Cache-control: private

     
    <html>
    <head>
    <title>文件上传</title>
    </head>
    <body>
    <font size=2>文件上传成功 [ <a href=# onclick=history.go(-1)>继续上传</a> ]</font>
    </body>
    </html>

     最后贴一下这个类的源代码:

    =======================================================
    首先是头文件:SendData.h

    // SendData.h: interface for the CSendData class.
    //
    //////////////////////////////////////////////////////////////////////

    #if !defined(AFX_SENDDATA_H__F98D6FB7_D797_4947_A17E_13E88D20F35F__INCLUDED_)
    #define AFX_SENDDATA_H__F98D6FB7_D797_4947_A17E_13E88D20F35F__INCLUDED_

    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000

    #include <afxinet.h>
    #include <string>
    using std::string;

    #define HTTP_POST_GB2312 1 //发送和接收的网页编码
    #define HTTP_POST_UTF8  2

    class CSendData 
    {
    public:
     CSendData();
     virtual ~CSendData();
     void SetServerParam(TCHAR ServerName[100],TCHAR ObjectName[100],WORD Port);
     //构造协议数据内容
     BOOL MakePostData(LPCTSTR pPostName, LPCTSTR pPostValue);
     BOOL MakePostData(LPCTSTR pPostName,int iPostValue);
     //发送带图片的数据
     DWORD PostPicDataMethod(TCHAR PicPath[MAX_PATH],LPCTSTR pPostName,
      LPTSTR *pRecvData, DWORD &RecvSize,
      int SendCode = HTTP_POST_GB2312,//发送和接收的编码
      int RecvCode = HTTP_POST_GB2312); 
     //发送文本类数据
     DWORD PostDataMethod(LPCTSTR strDataSend, int DataSize,
      LPTSTR *pRecvData, DWORD &RecvSize,
      int SendCode = 1,int RecvCode = 1);
    private:
     CString   m_strBoundary; //数据分隔符
     CString   m_strHeaderData; //协议头数据
     CString   m_strPostData; //协议正文数据
     CString   m_strEndData; //协议尾数据

     void MakeHeaderData(); //构造协议头部数据
     void MakeEndData();  //构造协议尾部数据
     void MakePostPicData(LPCTSTR pPostName, LPCTSTR pPostValue); //构造图片前缀数据

     //返回值为图片大小,返回值为0表示不存在。
     DWORD GetExistPic(TCHAR PicPath[MAX_PATH]);
     //服务器参数
     INTERNET_PORT m_nPort; 
     TCHAR m_tzObjectName[100];
     TCHAR m_tzServerName[100];
     /////编码转换/////////////////////////////////////////////////////////////
     char * m_lpUTF8;   //UTF8编码缓存指针
     char * m_lpMultiByte; //Multil多字节编码指针
     wchar_t * m_wpWideChar;  //Widechar编码缓存指针
     int  m_nUTF8Len; 
     int  m_nMultiByteLen;
     int  m_nWideCharLen;
     
     void WideCharToUTF8(LPCWSTR wpWideData, int WideLen);
     void MultiByteToUTF8(LPCSTR lpMultiData, int MultiLen);
     void UTF8ToWideChar(LPCSTR pUTF8,int UTF8Len);
     void UTF8ToMultiByte(LPCSTR pUTF8, int UTF8Len);
     void MultiToWide(LPCSTR strDataSend, int DataSize);
     void MultiToMulti(LPCSTR strDataSend, int DataSize);
     void WideToMulti(LPCWSTR wpWideData, int WideLen);

    };

    #endif // !defined(AFX_SENDDATA_H__F98D6FB7_D797_4947_A17E_13E88D20F35F__INCLUDED_)

    ========================================================
    接着是SendData.cpp文件。

    // UploadPhotoDlg.cpp : implementation file
    //

    #include "stdafx.h"
    #include "UploadPhoto.h"
    #include "UploadPhotoDlg.h"

    #include "SendData.h"

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif

    /////////////////////////////////////////////////////////////////////////////
    // CUploadPhotoDlg dialog

    CUploadPhotoDlg::CUploadPhotoDlg(CWnd* pParent /*=NULL*/)
     : CDialog(CUploadPhotoDlg::IDD, pParent)
    {
     //{{AFX_DATA_INIT(CUploadPhotoDlg)
     m_strPhotoPath = _T("");
     m_nPort = 80;
     m_strRecvData = _T("");
    //  m_strObjectName = _T("/frontend_dev.php/device/retriever");
    //  m_strServerName = _T("trunk.xunhui1.net");
     m_strObjectName = _T("/upload.asp");
     m_strServerName = _T("192.168.2.111");
     m_PostName = _T("userid");
     m_PostValue = _T("27EF272F28239E5A34EE223FADFWAFAEaE");
     //}}AFX_DATA_INIT
     // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    }

    void CUploadPhotoDlg::DoDataExchange(CDataExchange* pDX)
    {
     CDialog::DoDataExchange(pDX);
     //{{AFX_DATA_MAP(CUploadPhotoDlg)
     DDX_Text(pDX, IDC_EDIT_OBJECTNAME, m_strObjectName);
     DDX_Text(pDX, IDC_EDIT_PHOTOPATH, m_strPhotoPath);
     DDX_Text(pDX, IDC_EDIT_PORT, m_nPort);
     DDX_Text(pDX, IDC_EDIT_RECVDATA, m_strRecvData);
     DDX_Text(pDX, IDC_EDIT_SERVERNAME, m_strServerName);
     DDX_Text(pDX, IDC_EDIT_POSTDATANAME, m_PostName);
     DDX_Text(pDX, IDC_EDIT_POSTDATAVALUE, m_PostValue);
     //}}AFX_DATA_MAP
    }

    BEGIN_MESSAGE_MAP(CUploadPhotoDlg, CDialog)
     //{{AFX_MSG_MAP(CUploadPhotoDlg)
     ON_WM_PAINT()
     ON_WM_QUERYDRAGICON()
     ON_BN_CLICKED(IDC_BTN_SEND, OnBtnSend)
     ON_BN_CLICKED(IDC_BTN_FILEOPEN, OnBtnFileopen)
     //}}AFX_MSG_MAP
    END_MESSAGE_MAP()

    /////////////////////////////////////////////////////////////////////////////
    // CUploadPhotoDlg message handlers

    BOOL CUploadPhotoDlg::OnInitDialog()
    {
     CDialog::OnInitDialog();

     // Set the icon for this dialog.  The framework does this automatically
     //  when the application's main window is not a dialog
     SetIcon(m_hIcon, TRUE);   // Set big icon
     SetIcon(m_hIcon, FALSE);  // Set small icon
     
     // TODO: Add extra initialization here
     ((CButton*)GetDlgItem(IDC_RADIO_SENDGB2312))->SetCheck(TRUE);
     ((CButton*)GetDlgItem(IDC_RADIO_RECVGB2312))->SetCheck(TRUE);

     return TRUE;  // return TRUE  unless you set the focus to a control
    }

    // If you add a minimize button to your dialog, you will need the code below
    //  to draw the icon.  For MFC applications using the document/view model,
    //  this is automatically done for you by the framework.

    void CUploadPhotoDlg::OnPaint()
    {
     if (IsIconic())
     {
      CPaintDC dc(this); // device context for painting

      SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

      // Center icon in client rectangle
      int cxIcon = GetSystemMetrics(SM_CXICON);
      int cyIcon = GetSystemMetrics(SM_CYICON);
      CRect rect;
      GetClientRect(&rect);
      int x = (rect.Width() - cxIcon + 1) / 2;
      int y = (rect.Height() - cyIcon + 1) / 2;

      // Draw the icon
      dc.DrawIcon(x, y, m_hIcon);
     }
     else
     {
      CDialog::OnPaint();
     }
    }

    // The system calls this to obtain the cursor to display while the user drags
    //  the minimized window.
    HCURSOR CUploadPhotoDlg::OnQueryDragIcon()
    {
     return (HCURSOR) m_hIcon;
    }

    void CUploadPhotoDlg::OnBtnSend()
    {
     // TODO: Add your control notification handler code here
     GetDlgItem(IDC_BTN_SEND)->EnableWindow(FALSE);
     
     UpdateData(TRUE);
     //定义发送类
     CSendData MySend; 
     TCHAR  *pRecvData = NULL; //接收数据的指针
     DWORD  dwRecvSize = 0;  //接收数据的大小
     DWORD  dwRetSend = 0;  //发送函数返回值
     int   SendCode = HTTP_POST_GB2312,RecvCode =HTTP_POST_GB2312; //发送与接收的编码
     //设置服务器参数
     MySend.SetServerParam((LPTSTR)(LPCTSTR)m_strServerName,(LPTSTR)(LPCTSTR)m_strObjectName,m_nPort);

     //确定发送方法
     if (1 == ((CButton*)GetDlgItem(IDC_RADIO_SENDGB2312))->GetCheck())
     {
      SendCode = HTTP_POST_GB2312;
     }
     else
     {
      SendCode = HTTP_POST_UTF8;
     }
     //确定接收编码
     if (1 == ((CButton*)GetDlgItem(IDC_RADIO_RECVGB2312))->GetCheck())
     {
      RecvCode = HTTP_POST_GB2312;
     }
     else
     {
      RecvCode = HTTP_POST_UTF8;
     }
     //必须先构造数据包
     MySend.MakePostData(_T("Crypt"),_T("10"));
     MySend.MakePostData(_T("type"),_T("200"));
     MySend.MakePostData(m_PostName,m_PostValue);
     //发送
     dwRetSend = MySend.PostPicDataMethod((LPTSTR)(LPCTSTR)m_strPhotoPath,_T("filename"),
      &pRecvData,dwRecvSize,
      SendCode,RecvCode);
     //处理接收数据
     //99:图片不存在
     //100:正常成功
     //101:服务器无法连接
     //102:提交页面无法打开
     //103:数据发送失败
     //104:服务器处理失败
     //500:异常错误
     if (dwRetSend == 100)
     {
      MessageBox(_T("发送成功"));
     }
     else if (dwRetSend == 99 )
     {
      MessageBox(_T("发送成功"));
     }
     else if (dwRetSend == 101 )
     {
      MessageBox(_T("服务器无法连接"));
     }
     else if (dwRetSend == 102 )
     {
      MessageBox(_T("提交页面无法打开"));
     }
     else if (dwRetSend == 103 )
     {
      MessageBox(_T("数据发送失败"));
     }
     else if (dwRetSend == 104 )
     {
      MessageBox(_T("服务器处理失败"));
     }
     else if (dwRetSend == 500 )
     {
      MessageBox(_T("异常错误"));
     }
     //更新返回数据框
     m_strRecvData = pRecvData;
     UpdateData(FALSE);
      
     GetDlgItem(IDC_BTN_SEND)->EnableWindow(TRUE);

    }

    void CUploadPhotoDlg::OnBtnFileopen()
    {
     // TODO: Add your control notification handler code here
     TCHAR tzFilter[] = _T("jpg图片(*.jpg;*.jpeg)|*.jpg;*.jpeg|gif图片(*.gif)|*.gif|所有文件(*.*)|*.*||");
     CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_ENABLESIZING|OFN_EXPLORER,
      tzFilter,NULL);
     if (dlg.DoModal() == IDOK)
     {
      m_strPhotoPath = dlg.GetPathName();
      UpdateData(FALSE);
     }

    }
  • 相关阅读:
    #define #undef
    ps
    Find–atime –ctime –mtime的用法与区别总结
    redis
    linux mutex
    private继承
    boost::noncopyable介绍
    Makefile 中:= ?= += =的区别
    linux Tar 命令参数详解
    Ubuntu14.04安装CMake3.0.2
  • 原文地址:https://www.cnblogs.com/yaoliang11/p/1860312.html
Copyright © 2011-2022 走看看