使用HTTP/HTTPS上传、下载文件

这两天做了使用HTTPS协议上传、下载文件的项目,终于折腾通了。在此贴上代码,便于自己学习,也许还能帮助遇到类似问题 的人。

//1、HTTP/HTTPS下载文件

bool Download(LPCTSTR strFileURLInServer, //待下载文件的URL
              LPCTSTR strFileLocalFullPath)//存放到本地的路径
{
    ASSERT(strFileURLInServer != "");
    ASSERT(strFileLocalFullPath != "");
    CInternetSession session;
    CHttpConnection* pHttpConnection = NULL;
    CHttpFile* pHttpFile = NULL;
    CString strServer, strObject;
    INTERNET_PORT wPort;

    DWORD dwType, dwFlags;
    const int nTimeOut = 2000;
    session.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, nTimeOut); //重试之间的等待延时
    session.SetOption(INTERNET_OPTION_CONNECT_RETRIES, 1);   //重试次数
    char* pszBuffer = NULL;  

    AfxParseURL(strFileURLInServer, dwType, strServer, strObject, wPort);

    dwFlags = 0;
    if (dwType == AFX_INET_SERVICE_HTTPS)
    {
        dwFlags = INTERNET_FLAG_SECURE |  
            INTERNET_FLAG_EXISTING_CONNECT |  
            INTERNET_FLAG_RELOAD |  
            INTERNET_FLAG_NO_CACHE_WRITE |  
            INTERNET_FLAG_IGNORE_CERT_DATE_INVALID |  
            INTERNET_FLAG_IGNORE_CERT_CN_INVALID;  
    }


    try
    {       
        pHttpConnection = session.GetHttpConnection(strServer, wPort);
        pHttpFile = pHttpConnection->OpenRequest(CHttpConnection::HTTP_VERB_GET, strObject,
            NULL, 1, NULL, NULL, dwFlags);   


        if (dwType == AFX_INET_SERVICE_HTTPS)
        {
            //忽略证书
            pHttpFile->QueryOption(INTERNET_OPTION_SECURITY_FLAGS, dwFlags);  
            dwFlags |= (SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
                SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
                SECURITY_FLAG_IGNORE_UNKNOWN_CA  |
                SECURITY_FLAG_IGNORE_WRONG_USAGE |
                SECURITY_FLAG_IGNORE_REVOCATION);
            //set web server option   
            BOOL s = pHttpFile->SetOption(INTERNET_OPTION_SECURITY_FLAGS, dwFlags); 
        }

        if(pHttpFile->SendRequest() == FALSE)
            return false;
        DWORD dwStateCode;

        pHttpFile->QueryInfoStatusCode(dwStateCode);
        if(dwStateCode == HTTP_STATUS_OK)
        {
            HANDLE hFile = CreateFile(strFileLocalFullPath, GENERIC_WRITE,
                FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
                NULL);  //创建本地文件
            if(hFile == INVALID_HANDLE_VALUE)
            {
                pHttpFile->Close();
                pHttpConnection->Close();
                session.Close();
                return false;
            }


            char szInfoBuffer[1000];  //返回消息
            DWORD dwFileSize = 0;   //文件长度
            DWORD dwInfoBufferSize = sizeof(szInfoBuffer);
            BOOL bResult = FALSE;
            bResult = pHttpFile->QueryInfo(HTTP_QUERY_CONTENT_LENGTH,
                (void*)szInfoBuffer,&dwInfoBufferSize,NULL);

            dwFileSize = atoi(szInfoBuffer);

            const int BUFFER_LENGTH = 1024 * 10;
            pszBuffer = new char[BUFFER_LENGTH];  //读取文件的缓冲
            DWORD dwWrite, dwTotalWrite;
            dwWrite = dwTotalWrite = 0;
            UINT nRead = pHttpFile->Read(pszBuffer, BUFFER_LENGTH); //读取服务器上数据

            while(nRead > 0)
            {
                WriteFile(hFile, pszBuffer, nRead, &dwWrite, NULL);  //写到本地文件
                dwTotalWrite += dwWrite;
                nRead = pHttpFile->Read(pszBuffer, BUFFER_LENGTH);
            }

            delete[]pszBuffer;
            pszBuffer = NULL;
            CloseHandle(hFile);
        }
        else
        {
            delete[]pszBuffer;
            pszBuffer = NULL;
            if(pHttpFile != NULL)
            {
                pHttpFile->Close();
                delete pHttpFile;
                pHttpFile = NULL;
            }
            if(pHttpConnection != NULL)
            {
                pHttpConnection->Close();
                delete pHttpConnection;
                pHttpConnection = NULL;
            }
            session.Close();
            return false;
        }
    }
    catch(...)
    {
        delete[]pszBuffer;
        pszBuffer = NULL;
        if(pHttpFile != NULL)
        {
            pHttpFile->Close();
            delete pHttpFile;
            pHttpFile = NULL;
        }
        if(pHttpConnection != NULL)
        {
            pHttpConnection->Close();
            delete pHttpConnection;
            pHttpConnection = NULL;
        }
        session.Close();
        return false;
    }


    if(pHttpFile != NULL)
        pHttpFile->Close();
    if(pHttpConnection != NULL)
        pHttpConnection->Close();
    session.Close();
    return true;
}

//2、HTTP/HTTPS上传文件UploadFile();

CString MakeRequestHeaders(CString &strBoundary)//包头    
{   
    CString strFormat;   
    CString strData;   

    strFormat = _T("Content-Type: multipart/form-data; boundary=%s\r\n");

    strData.Format(strFormat, strBoundary);   
    return strData;   
}   


CString MakePreFileData(CString &strBoundary, CString &strFileName, int iRecordID)   
{
    CString strFormat;   
    CString strData;   

    strFormat += _T("--%s");   
    strFormat += _T("\r\n");   
    strFormat += _T("Content-Disposition: form-data; name=\"fuck\"");    
    strFormat += _T("\r\n\r\n");   
    strFormat += _T("jump");   
    strFormat += _T("\r\n");   

    strFormat += _T("--%s");
    strFormat += _T("\r\n");
    strFormat += _T("Content-Disposition: form-data; name=\"fileupload\"; filename=\"%s\"");//文件地址信息    
    strFormat += _T("\r\n");
    strFormat += _T("Content-Type: application/octet-stream");

    strFormat += _T("\r\n\r\n");
    //strData.Format(strFormat,  strBoundary,  strFileName);

    strData.Format(strFormat,  strBoundary,strBoundary,  strFileName);
    return strData;   
}


CString MakePostFileData(CString &strBoundary)//发送请求包    
{
    CString strFormat;   
    CString strData;   

    strFormat = _T("\r\n\r\n");
    strFormat += _T("--%s--");   
    strFormat += _T("\r\n");   

    strData.Format(strFormat, strBoundary, strBoundary);   

    return strData;   



BOOL UploadFile(LPCTSTR fileUrl, LPCTSTR file)
{
    CInternetSession Session;   
    CHttpConnection *pHttpConnection = NULL;   
    INTERNET_PORT   nPort;   
    CFile fTrack;   
    CHttpFile* pHTTP;   
    CString strHTTPBoundary;   
    CString strPreFileData;   
    CString strPostFileData;   
    DWORD dwTotalRequestLength;   
    DWORD dwChunkLength;   
    DWORD dwReadLength;   
    DWORD dwResponseLength;   
    TCHAR szError[MAX_PATH];   
    void* pBuffer;   
    LPSTR szResponse;   
    CString strResponse;   
    BOOL bSuccess = TRUE;   

    CString localFile;   
    DWORD dwServiceType, dwFlags;

    localFile = file;//要传的本地文件地址    
    int startp = localFile.ReverseFind('\\');   
    int namelen = localFile.GetLength()-startp-1;   

    CString pcmname = localFile;  

    CString defServerName;//服务器名    
    CString defObjectName;//保存的地址

    CString serverPath = fileUrl;
    AfxParseURL(serverPath, dwServiceType, defServerName, defObjectName, nPort);

    dwFlags = 0;
    if (dwServiceType == AFX_INET_SERVICE_HTTPS)
    {
        dwFlags = INTERNET_FLAG_SECURE |  
            INTERNET_FLAG_EXISTING_CONNECT |  
            INTERNET_FLAG_RELOAD |  
            INTERNET_FLAG_NO_CACHE_WRITE |  
            INTERNET_FLAG_IGNORE_CERT_DATE_INVALID |  
            INTERNET_FLAG_IGNORE_CERT_CN_INVALID;  
    }

    CString strDebugMessage;   

    if(FALSE == fTrack.Open(localFile, CFile::modeRead | CFile::shareDenyWrite))//读出文件     
    {
        return FALSE;   
    }   

    int iRecordID = 1;   
    strHTTPBoundary = _T("-------------2389jhrwfjsjd9823");//定义边界值    
    strPreFileData = MakePreFileData(strHTTPBoundary, pcmname, iRecordID);   
    strPostFileData = MakePostFileData(strHTTPBoundary);   

    dwTotalRequestLength = strPreFileData.GetLength() + strPostFileData.GetLength() + fTrack.GetLength();//计算整个包的总长度    

    dwChunkLength = 64 * 1024;   

    pBuffer = malloc(dwChunkLength);   

    if (NULL == pBuffer)   
    {   
        return FALSE;   
    }   

    try   
    {   
        pHttpConnection = Session.GetHttpConnection(defServerName,nPort);   
        pHTTP = pHttpConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST, defObjectName, 
            NULL, 1, NULL, NULL, dwFlags);   

        if (dwServiceType == AFX_INET_SERVICE_HTTPS)
        {
        //忽略证书
            pHTTP->QueryOption(INTERNET_OPTION_SECURITY_FLAGS, dwFlags);  
            dwFlags |= (SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
                SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
                SECURITY_FLAG_IGNORE_UNKNOWN_CA  |
                SECURITY_FLAG_IGNORE_WRONG_USAGE |
                SECURITY_FLAG_IGNORE_REVOCATION);
            //set web server option   
            BOOL s = pHTTP->SetOption(INTERNET_OPTION_SECURITY_FLAGS, dwFlags); 
        }

        pHTTP->AddRequestHeaders(MakeRequestHeaders(strHTTPBoundary));//发送包头请求    
        pHTTP->SendRequestEx(dwTotalRequestLength, HSR_SYNC | HSR_INITIATE);   

#ifdef _UNICODE
        pHTTP->Write(W2A(strPreFileData), strPreFileData.GetLength());   
#else    
        pHTTP->Write((LPSTR)(LPCSTR)strPreFileData, strPreFileData.GetLength());//写入服务器所需信息    
#endif    
        dwReadLength = -1;   
        while (0 != dwReadLength)   
        {   
            strDebugMessage.Format(_T("%u / %u\n"), fTrack.GetPosition(), fTrack.GetLength());   
            TRACE(strDebugMessage);   
            dwReadLength = fTrack.Read(pBuffer, dwChunkLength);//文件内容    
            if (0 != dwReadLength)   
            {   
                pHTTP->Write(pBuffer, dwReadLength);//写入服务器本地文件,用二进制进行传送    
            }   
        }   

#ifdef _UNICODE
        pHTTP->Write(W2A(strPostFileData), strPostFileData.GetLength());   
#else    
        pHTTP->Write((LPSTR)(LPCSTR)strPostFileData, strPostFileData.GetLength());   
#endif
        pHTTP->EndRequest(HSR_SYNC);   
        dwResponseLength = pHTTP->GetLength();   
        while (0 != dwResponseLength)   
        {   
            szResponse = (LPSTR)malloc(dwResponseLength + 1);   
            szResponse[dwResponseLength] = '\0';   
            pHTTP->Read(szResponse, dwResponseLength);   
            strResponse += szResponse;   
            free(szResponse);   
            dwResponseLength = pHTTP->GetLength();   
        }   
    }    
    catch (CException* e)   
    {   
        e->GetErrorMessage(szError, MAX_PATH);   
        e->Delete();   
        AfxMessageBox(szError);   
        bSuccess = FALSE;   
    }   


    pHTTP->Close();   
    delete pHTTP;   

    fTrack.Close();   


    if (NULL != pBuffer)   
    {   
        free(pBuffer);   
    }   
    return bSuccess;   
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值