note : make a class, use wininet api upload http file

来源:互联网 发布:创维电视怎么连接网络 编辑:程序博客网 时间:2024/05/16 18:57

今天工作中遇到了要向http上载服务器传文件的功能.

查到有2种方法做这事:

* 直接向http上载目录里用POST方法写文件.

* 假设有服务端的提交网页, 模拟网页提交文件.

我采用了最简单的第一种方法.


从网上找到一段代码, 整理了一个类, 参数变成活的了, 根据入参在类内部处理.

不记得从哪里找的了,  感谢~


整理后的类,用起来很简单。符合我的应用(给定一个本地文件全路径, 给定一个http远程文件夹全路径, 上传文件, 在远程存成一个随机的唯一文件名).

上载目录在服务器端用HFS搭建, 权限是任何人. 如果没有给定那个文件夹的上传权限,上传会失败.

上传中,没有使用用户名和口令.

类实现中,有一些工具函数(e.g. 取路径, 字符串格式化), 没有贴上。


调用端代码:

    std::wstring    strRemoteFilePathName = L"";    CHttpUpLoader   uploader;    uploader.uploadHttpFile(        pcZipPathName,        ns_business::GetUrl_HttpUpload(),        TRUE,        strRemoteFilePathName);
http文件上传类实现:

/// @file       httpUploader.h/// @brief      向http上传服务器给定的文件夹上传文件#ifndef __HTTP_UP_LOADER_H__#define __HTTP_UP_LOADER_H__class CHttpUpLoader{public:    CHttpUpLoader();    ~CHttpUpLoader();    BOOL uploadHttpFile(        IN const WCHAR * pcLocalFilePathName,       ///< 本地文件全路径名称        IN const WCHAR * pcRemoteUploadDirPathName, ///< 远程http文件夹名称         IN BOOL bAutoRename,                        ///< 是否自动改名, 保证远程文件名唯一        OUT std::wstring & strRemoteFilePathName);  ///< 保存后的远程文件全路径private:    void DataInit();    void SetLocalFilePathName(const WCHAR * pcLocalFilePathName);    const WCHAR * GetLocalFilePathName();    void SetRemoteUploadDirPathName(const WCHAR * pcRemoteUploadDirPathName);    const WCHAR * GetRemoteUploadDirPathName();    void SetRemoteFilePathName(const WCHAR * pcRemoteFilePathName);    const WCHAR * GetRemoteFilePathName();    void SetAutoRename(BOOL bAutoRename);    BOOL GetAutoRename();    const WCHAR * GetReferer();    void SetUrlSchema(const WCHAR * pcIn);    const WCHAR * GetUrlSchema();    void SetIp(const WCHAR * pcIn);    const WCHAR * GetIp();    void SetHttpPort(const WCHAR * pcIn);    const WCHAR * GetHttpPort();    void SetSite(const WCHAR * pcIn);    const WCHAR * GetSite();    void SetUrlPath(const WCHAR * pcIn);    const WCHAR * GetUrlPath();    void SetRemoteFileName(const WCHAR * pcIn);    const CHAR * GetRemoteFileNameA();    void GernerateRemoteFileName();    void SetFilePostfix(const WCHAR * pcFilePostfix);    const WCHAR * GetFilePostfix();    const WCHAR * GetBoundaryW();    const char * GetBoundaryA();private:    std::wstring    m_strLocalFilePathName;    std::wstring    m_strRemoteUploadDirPathName;    std::wstring    m_strRemoteFilePathName;    BOOL            m_bAutoRename;    std::wstring    m_strUrlSchema; // http    std::wstring    m_strIp; // 10.10.10.10    std::wstring    m_strHttpPort; // 6666 需要自己去找, 分析不出来    std::wstring    m_strSite; // http://10.10.10.10    std::wstring    m_strUrlPath; // /upload/    std::wstring    m_strRemoteFileName;    std::string     m_strRemoteFileNameA;    std::wstring    m_strFilePostfix;   ///< 文件后缀    std::wstring    m_strBoundaryW;    std::string     m_strBoundaryA;};#endif

/// @file       httpUploader.cpp#include "stdafx.h"#include "httpUploader.h"#include <WinInet.h>#pragma comment(lib, "Wininet.lib")#include <Urlmon.h>#pragma comment(lib, "Urlmon.lib")CHttpUpLoader::CHttpUpLoader(){    DataInit();}CHttpUpLoader::~CHttpUpLoader(){}void CHttpUpLoader::DataInit(){    SetLocalFilePathName(L"");    SetRemoteUploadDirPathName(L"");    SetRemoteFilePathName(L"");    SetAutoRename(TRUE);    SetUrlSchema(L"");    SetIp(L"");    SetHttpPort(L"");    SetSite(L"");    SetUrlPath(L"");    SetRemoteFileName(L"");    SetFilePostfix(L"");}void CHttpUpLoader::SetLocalFilePathName(const WCHAR * pcLocalFilePathName){    size_t  nPos = 0;    m_strLocalFilePathName = (NULL != pcLocalFilePathName) ? pcLocalFilePathName : L"";    nPos = m_strLocalFilePathName.rfind(L'.');    if (std::wstring::npos != nPos)    {        SetFilePostfix(m_strLocalFilePathName.substr(nPos + 1, -1).c_str());    }}void CHttpUpLoader::SetFilePostfix(const WCHAR * pcFilePostfix){    m_strFilePostfix = (NULL != pcFilePostfix) ? pcFilePostfix : L"";}const WCHAR * CHttpUpLoader::GetFilePostfix(){    return m_strFilePostfix.c_str();}const WCHAR * CHttpUpLoader::GetLocalFilePathName(){    return m_strLocalFilePathName.c_str();}void CHttpUpLoader::SetRemoteUploadDirPathName(const WCHAR * pcRemoteUploadDirPathName){    m_strRemoteUploadDirPathName = (NULL != pcRemoteUploadDirPathName) ? pcRemoteUploadDirPathName : L"";    /// m_strRemoteUploadDirPathName like http://10.10.10.10:6666/upload/    size_t          nPos = std::wstring::npos;    size_t          nPosTemp = std::wstring::npos;    WCHAR szDecodedUrl[INTERNET_MAX_URL_LENGTH];    DWORD cchDecodedUrl = INTERNET_MAX_URL_LENGTH;    WCHAR szOut[INTERNET_MAX_URL_LENGTH];    if (!m_strRemoteUploadDirPathName.empty())    {        // m_strRemoteUploadDirPathName = http://10.10.10.10:6666/upload/        // szDecodedUrl = http://10.10.10.10:6666/upload/        HRESULT hr = CoInternetParseUrl(m_strRemoteUploadDirPathName.c_str(), PARSE_CANONICALIZE, URL_UNESCAPE, szDecodedUrl,             INTERNET_MAX_URL_LENGTH, &cchDecodedUrl, 0);        if (SUCCEEDED(hr))        {            hr = CoInternetParseUrl(szDecodedUrl, PARSE_SCHEMA, 0, szOut,                 INTERNET_MAX_URL_LENGTH, &cchDecodedUrl, 0);            if (SUCCEEDED(hr))                SetUrlSchema(szOut); // http            hr = CoInternetParseUrl(szDecodedUrl, PARSE_DOMAIN, 0, szOut,                 INTERNET_MAX_URL_LENGTH, &cchDecodedUrl, 0);            if (SUCCEEDED(hr))                SetIp(szOut); // 10.10.10.10            hr = CoInternetParseUrl(szDecodedUrl, PARSE_ROOTDOCUMENT, 0, szOut,                 INTERNET_MAX_URL_LENGTH, &cchDecodedUrl, 0);            if (SUCCEEDED(hr))                SetSite(szOut); // http://10.10.10.10            nPos = m_strRemoteUploadDirPathName.find(m_strSite.c_str(), 0);            if (std::wstring::npos != nPos)            {                SetHttpPort(L"80");                nPosTemp = nPos + _tcslen(m_strSite.c_str());                nPos = nPosTemp;                if (L':' == m_strRemoteUploadDirPathName[nPosTemp])                {                    // port is given, not default port 80                    nPos = m_strRemoteUploadDirPathName.find(L"/", ++nPosTemp);                    if (nPos != std::wstring::npos)                        SetHttpPort(m_strRemoteUploadDirPathName.substr(nPosTemp, nPos - nPosTemp).c_str());                    nPos = nPosTemp + _tcslen(m_strHttpPort.c_str());                }                SetUrlPath(m_strRemoteUploadDirPathName.substr(nPos, -1).c_str());            }        }    }}const WCHAR * CHttpUpLoader::GetRemoteUploadDirPathName(){    return m_strRemoteUploadDirPathName.c_str();    }void CHttpUpLoader::SetRemoteFilePathName(const WCHAR * pcRemoteFilePathName){    m_strRemoteFilePathName = (NULL != pcRemoteFilePathName) ? pcRemoteFilePathName : L"";}const WCHAR * CHttpUpLoader::GetRemoteFilePathName(){    return m_strRemoteFilePathName.c_str();}void CHttpUpLoader::SetAutoRename(BOOL bAutoRename){    m_bAutoRename = bAutoRename;}BOOL CHttpUpLoader::GetAutoRename(){    return m_bAutoRename;}const WCHAR * CHttpUpLoader::GetReferer(){    return GetRemoteUploadDirPathName();}const WCHAR * CHttpUpLoader::GetBoundaryW(){    // L"-----------------------------67491722032265"    // L"----------------------------06749,17220,32265"    m_strBoundaryW = ns_base::StringFormatV(L"-----------------------------%5.5d%5.5d%5.5d",        rand(),        rand(),        rand());    return m_strBoundaryW.c_str();}const char * CHttpUpLoader::GetBoundaryA(){    /// please call GetBoundaryW first, then call me    USES_CONVERSION;    m_strBoundaryA = W2A(m_strBoundaryW.c_str());    return m_strBoundaryA.c_str();}BOOL CHttpUpLoader::uploadHttpFile(    IN const WCHAR * pcLocalFilePathName,    IN const WCHAR * pcRemoteUploadDirPathName,    IN BOOL bAutoRename,    OUT std::wstring & strRemoteFilePathName){    SetLocalFilePathName(pcLocalFilePathName);    SetRemoteUploadDirPathName(pcRemoteUploadDirPathName);    SetAutoRename(bAutoRename);    GernerateRemoteFileName();    std::string    strContentDispos = "";    HINTERNET hSession=0;    HINTERNET hConnect=0;    HINTERNET hRequest=0;        DWORD dwNumberOfBytesWritten=0;    DWORD dwBytesSend=0;        INTERNET_BUFFERS BufferIn;    DWORD dwFlag;    LPCTSTR boundary = GetBoundaryW(); //随机字符串    LPCSTR aboundary =  GetBoundaryA(); //ansi    HANDLE hFile;    hFile = CreateFile(pcLocalFilePathName,        GENERIC_READ,        FILE_SHARE_READ|FILE_SHARE_WRITE,        0,        OPEN_EXISTING,        FILE_ATTRIBUTE_NORMAL,        0);    DWORD dwFileSize = GetFileSize(hFile, 0);        TCHAR content_type[128];    _stprintf_s(content_type,TEXT("Content-Type: multipart/form-data; boundary=%s"),boundary);        LPTSTR accept=TEXT("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");    LPTSTR accept_lan=TEXT("Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");    LPTSTR accept_encoding=TEXT("Accept-Encoding: gzip, deflate");    LPTSTR user_agent=TEXT("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0");    hSession=InternetOpen(_T("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0"),        INTERNET_OPEN_TYPE_PRECONFIG,        0,        INTERNET_INVALID_PORT_NUMBER,        0);    if (0==hSession)    {        return FALSE;    }    hConnect=InternetConnect(hSession,        GetIp(),        _ttoi(GetHttpPort()),        _T(""),        _T(""),        INTERNET_SERVICE_HTTP,        0,        0);    if (0==hConnect)    {        InternetCloseHandle(hSession);        return FALSE;    }    dwFlag=INTERNET_FLAG_KEEP_CONNECTION;    hRequest=HttpOpenRequest(hConnect,        _T("POST"),        GetUrlPath(),        HTTP_VERSION,        0,                //Referrer        0,                //AcceptTypes         dwFlag,        0);    if (NULL == hRequest)    {        InternetCloseHandle(hConnect);        InternetCloseHandle(hSession);        return FALSE;    }    HttpAddRequestHeaders(hRequest,content_type,-1,HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);    HttpAddRequestHeaders(hRequest,GetReferer(),-1,HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);    HttpAddRequestHeaders(hRequest,accept,-1,HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);    HttpAddRequestHeaders(hRequest,accept_lan,-1,HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);    HttpAddRequestHeaders(hRequest,accept_encoding,-1,HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);    BYTE* lpBuffer=(BYTE*)VirtualAlloc(0,dwFileSize,MEM_COMMIT,PAGE_READWRITE);    if (0==lpBuffer)    {        InternetCloseHandle(hRequest);        InternetCloseHandle(hConnect);        InternetCloseHandle(hSession);        return FALSE;    }    DWORD dwRead;    ReadFile(hFile,lpBuffer,dwFileSize,&dwRead,0);    CloseHandle(hFile);    char first_boundary[128];    char delimiter[128];    char end_boundary[128];    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);    strContentDispos = ns_base::StringFormatVA("Content-Disposition: form-data; name=\"file_upload\"; filename=\"%s\"\r\n",        GetRemoteFileNameA());    LPCSTR content_dispos = strContentDispos.c_str();        LPSTR content_type2="Content-Type: application/octet-stream\r\n\r\n";    LPSTR rn="\r\n";    BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS );    BufferIn.Next = NULL;     BufferIn.lpcszHeader = NULL;    BufferIn.dwHeadersLength = 0;    BufferIn.dwHeadersTotal = 0;    BufferIn.lpvBuffer = NULL;                    BufferIn.dwBufferLength = 0;    BufferIn.dwBufferTotal = dwFileSize        +strlen(first_boundary)        +strlen(content_dispos)        +strlen(content_type2)        +strlen(end_boundary); //Content-Length:    BufferIn.dwOffsetLow = 0;    BufferIn.dwOffsetHigh = 0;    if (!HttpSendRequestEx(hRequest,&BufferIn,0,0,0))    {        InternetCloseHandle(hRequest);        InternetCloseHandle(hConnect);        InternetCloseHandle(hSession);        return FALSE;    }    InternetWriteFile(hRequest,(byte*)first_boundary,strlen(first_boundary),&dwNumberOfBytesWritten); //first boundary    InternetWriteFile(hRequest,(byte*)content_dispos,strlen(content_dispos),&dwNumberOfBytesWritten);    InternetWriteFile(hRequest,(byte*)content_type2,strlen(content_type2),&dwNumberOfBytesWritten);    /// 分多次写远程文件, 就可以统计进度    InternetWriteFile(hRequest,lpBuffer,dwFileSize,&dwNumberOfBytesWritten);    //如果还有其他文件    //InternetWriteFile(hRequest,(byte*)delimiter,strlen(delimiter),&dwNumberOfBytesWritten); //deimiter    //InternetWriteFile(hRequest,(byte*)content_dispos,strlen(content_dispos),&dwNumberOfBytesWritten);    //InternetWriteFile(hRequest,(byte*)content_type2,strlen(content_type2),&dwNumberOfBytesWritten);    //...    InternetWriteFile(hRequest,(byte*)end_boundary,strlen(end_boundary),&dwNumberOfBytesWritten);//last boundary    HttpEndRequest(hRequest,0,0,0);    InternetCloseHandle(hRequest);    InternetCloseHandle(hConnect);    InternetCloseHandle(hSession);    VirtualFree(lpBuffer,0,MEM_RELEASE);    return TRUE;}void CHttpUpLoader::SetUrlSchema(const WCHAR * pcIn){    m_strUrlSchema = (NULL != pcIn) ? pcIn : L"";}const WCHAR * CHttpUpLoader::GetUrlSchema(){    return m_strUrlSchema.c_str();}void CHttpUpLoader::SetIp(const WCHAR * pcIn){    m_strIp = (NULL != pcIn) ? pcIn : L"";}const WCHAR * CHttpUpLoader::GetIp(){    return m_strIp.c_str();}void CHttpUpLoader::SetHttpPort(const WCHAR * pcIn){    m_strHttpPort = (NULL != pcIn) ? pcIn : L"";}const WCHAR * CHttpUpLoader::GetHttpPort(){    return m_strHttpPort.c_str();}void CHttpUpLoader::SetSite(const WCHAR * pcIn){    m_strSite = (NULL != pcIn) ? pcIn : L"";}const WCHAR * CHttpUpLoader::GetSite(){    return m_strSite.c_str();}void CHttpUpLoader::SetUrlPath(const WCHAR * pcIn){    m_strUrlPath = (NULL != pcIn) ? pcIn : L"";}const WCHAR * CHttpUpLoader::GetUrlPath(){    return m_strUrlPath.c_str();}void CHttpUpLoader::SetRemoteFileName(const WCHAR * pcIn){    m_strRemoteFileName = (NULL != pcIn) ? pcIn : L"";}const CHAR * CHttpUpLoader::GetRemoteFileNameA(){    USES_CONVERSION;    m_strRemoteFileNameA = W2A(m_strRemoteFileName.c_str());    return m_strRemoteFileNameA.c_str();}void CHttpUpLoader::GernerateRemoteFileName(){    std::wstring    strFileName = L"";    SYSTEMTIME stLocal;    GetLocalTime(&stLocal);    strFileName = ns_base::StringFormatV(L"%s_%4.4d%2.2d%2.2d_%2.2d%2.2d%2.2d_%3.3d_%5.5d.%s",         UPLOAD_FILE_TYPE,        stLocal.wYear,        stLocal.wMonth,        stLocal.wDay,        stLocal.wHour,        stLocal.wMinute,        stLocal.wSecond,        stLocal.wMilliseconds,        rand(),        GetFilePostfix());    SetRemoteFileName(strFileName.c_str());}




0 0