您的位置:首页 > 理论基础 > 计算机网络

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

2014-02-28 02:06 393 查看
今天工作中遇到了要向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());
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: