注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Simon

 
 
 

日志

 
 

Symbian(Http DownLoad)Http引擎下载  

2010-06-17 01:28:23|  分类: Symbian C++ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
前面二篇blog介绍了关于接入点的相关情况
今天让我们来看看下载是如何处理的
其实在SYMBIAN平台实现下载方式较多
比如直接用系统提供的HTTP引擎
比如有SOCKET模拟HTTP来实现

今天我们主要谈谈用平台的HTTP引警是如何实现的
也会在接下来的通信编程中聊聊socket模拟HTTP下载.

其实WIKI上给我们提供了一个关于HTTP下载的很好的例子.
并且网上也有很多关于这方面的资料.
我将主要谈谈比较关键的地方希望对后来的学习的朋友有一些帮助.

其实要完成整个HTTP下载官方提供的例子是不够的.
官方的例子只能让我们了解API的使用流程.
我们还需要处理各种异常,比如超时,比如跳转等等.
我们还要站在用户的角度去处理比如走WAP代理,比如断点续传等等.

好让我们少费话了直接进入主题吧!!嘎嘎!!!

首先介绍以下三个主要类:
//处理HTTP事物中的相关事件
//比如响应消息头,消息体,各种异常处理等
MHTTPTransactionCallback

//HTTP会话,建立客户端于内核的会话
RHTTPSession
//在会话的基础上建立下载事物
//一个http session可以有多个Transaction
//要实现多个事物同时进行必须要建立多个http session
RHTTPTransaction
经过上述基本介绍后,让我们看看具体的实现吧!!

//GET 请求
void CWebClientEngine::HTTPGetL(const TDesC8& aUri)
    {
    iDownloadSize = 0;
    bHttpGetOrPost = ETrue;
    //自己设置计时器,为超时作准备
    StartTimer(30);
    
    //为了二次连接,在WAP代理时首次连接会有移动拦截页回来
    //这样可以直接把当前连接再请求一次,即可以解决问题.
    iSecondUrl.Copy(aUri);
    TUriParser8 uri;
    uri.Parse(aUri);

#ifndef _DEBUG//不在DEBUG的情况下
    if (bIAPIsWap)//如果是WAP接入点,需要设置WAP代理
        {
        //中国特色,不要报怨.
        //改变不了社会,就加代码.嘎嘎!!
        TBuf8<20> aProxy8(_L8("10.0.0.172:80"));
        RStringF iPrxAddr = iSession.StringPool().OpenFStringL(aProxy8);
        CleanupClosePushL(iPrxAddr);
        THTTPHdrVal iPrxUsage(iSession.StringPool().StringF

(HTTP::EUseProxy,RHTTPSession::GetTable()));
        iSession.ConnectionInfo().SetPropertyL(iSession.StringPool().StringF

(HTTP::EProxyUsage,RHTTPSession::GetTable()), iPrxUsage);
        iSession.ConnectionInfo().SetPropertyL(iSession.StringPool().StringF

(HTTP::EProxyAddress,RHTTPSession::GetTable()), iPrxAddr);
        CleanupStack::PopAndDestroy();
        }
#endif

    // Get request method string for HTTP GET
    RStringF method = iSession.StringPool().StringF(HTTP::EGET,
            RHTTPSession::GetTable());

    // Open transaction with previous method and parsed uri. This class will
    // receive transaction events in MHFRunL and MHFRunError.
    iTransaction = iSession.OpenTransactionL(uri, *this, method);

    // Set headers for request; user agent and accepted content type
    RHTTPHeaders hdr = iTransaction.Request().GetHeaderCollection();
    SetHeaderL(hdr, HTTP::EUserAgent, KUserAgent);//设置UA
    SetHeaderL(hdr, HTTP::EAccept, KAccept);//设置accept    

    //设置代码续传
    TBuf8<64> sizeStr;
    sizeStr.Format (_L8("bytes=%d-"),iDownloadSize);
    sizeStr.AppendFormat (_L8("%d"),curSizeL);
    SetHeaderL (hdr, HTTP::ERange, sizeStr);

    // Submit the transaction. After this the framework will give transaction
    // events via MHFRunL and MHFRunError.
    iTransaction.SubmitL();//启动请求.请法度是一个异步的过程.
    //请求完成后,会在MHTTPTransactionCallback方法回调相关的事件.
    iRunning = ETrue;
    }

//POST 请求
void CWebClientEngine::HTTPPostL(const TDesC8& aUri, const TDesC8& aBody)
    {    
    iDownloadSize = 0;
    bHttpGetOrPost = EFalse;
    StartTimer(30);
    
    iSecondUrl.Copy(aUri);
    // Parse string to URI (as defined in RFC2396)
    TUriParser8 uri;
    uri.Parse(aUri);

    delete iPostData;
    iPostData = aBody.AllocL();

#ifndef _DEBUG
    if (bIAPIsWap)//设置WAP代理
        {
        TBuf8<20> aProxy8(_L8("10.0.0.172:80"));
        RStringF iPrxAddr = iSession.StringPool().OpenFStringL(aProxy8);
        CleanupClosePushL(iPrxAddr);
        THTTPHdrVal iPrxUsage(iSession.StringPool().StringF

(HTTP::EUseProxy,RHTTPSession::GetTable()));
        iSession.ConnectionInfo().SetPropertyL(iSession.StringPool().StringF

(HTTP::EProxyUsage,RHTTPSession::GetTable()), iPrxUsage);
        iSession.ConnectionInfo().SetPropertyL(iSession.StringPool().StringF

(HTTP::EProxyAddress,RHTTPSession::GetTable()), iPrxAddr);
        CleanupStack::PopAndDestroy();
        }
#endif

    RStringF method = iSession.StringPool().StringF(HTTP::EPOST,
            RHTTPSession::GetTable());

    // Open transaction with previous method and parsed uri. This class will
    // receive transaction events in MHFRunL and MHFRunError.
    iTransaction = iSession.OpenTransactionL(uri, *this, method);

    // Set headers for request; user agent and accepted content type
    RHTTPHeaders hdr = iTransaction.Request().GetHeaderCollection();
    SetHeaderL(hdr, HTTP::EUserAgent, KUserAgent);
    
    SetHeaderL(hdr, HTTP::EAccept, KAccept);
    SetHeaderL( hdr, HTTP::EContentType, _L8("text/xml"));

    //设置代码续传
    TBuf8<64> sizeStr;
    sizeStr.Format (_L8("bytes=%d-"),iDownloadSize);
    sizeStr.AppendFormat (_L8("%d"),curSizeL);
    SetHeaderL (hdr, HTTP::ERange, sizeStr);
    
    MHTTPDataSupplier* dataSupplier = this;
    iTransaction.Request().SetBody(*dataSupplier);

    // Submit the transaction. After this the framework will give transaction
    // events via MHFRunL and MHFRunError.
    iTransaction.SubmitL();

    iRunning = ETrue;
    }


//请求完成后,事物的相关事件都会回调
void CWebClientEngine::MHFRunL(RHTTPTransaction aTransaction,
        const THTTPEvent& aEvent)
    {
    switch (aEvent.iStatus)
        {
        //响应消息头
        case THTTPEvent::EGotResponseHeaders:
            {
            RHTTPResponse resp = aTransaction.Response();
            TInt status = resp.StatusCode();        

            if (status == 200 || status == 206)
                {
                //成功连接的情况下,解析头.
                DumpRespHeadersL(aTransaction);
                iObserver->HandleWebDataStart();
                }
            else if (status >= 300 && status <= 399)
                {
                iRunning = EFalse;
                //发生跳转时,得到跳转地址
                GetLocationL(aTransaction);
                iDownloadSize = 0;
                //得到跳转地址后,重新请求
                StartGetClient(m_Location,iDownloadSize);
                break;
                }
            else
                {
                //发生异常,关闭事物
                iTransaction.Close();
                iRunning = EFalse;
                break;
                }
            }
            break;
            
        case THTTPEvent::EGotResponseBodyData:
            {
            //响应消息体
            // Get the body data supplier
            MHTTPDataSupplier* body = aTransaction.Response().Body();
            TPtrC8 dataChunk;
            TBool isLast = body->GetNextDataPart(dataChunk);
            RLog::LogPoor(_L("isLast = "),isLast);
            DataLength = dataChunk.Length();
            bIsReciveData = ETrue;
            
            if(bIAPIsWap)//如果是WAP接入点.我们需要判断移动拦截页面
                {
                //如果是移动拦截页,再次请求
                TBool err = CheckRecv(dataChunk);
                RLog::LogPoor(_L("err = "),err);
                if(err == false)
                    {
                    body->ReleaseData();
                    CancelTransactionL();
                    //重新请求分二种情况
                    //GET请求,POST请求
                    if (bHttpGetOrPost)//get方法
                        {
                        iDownloadSize = 0;
                        StartGetClient(iSecondUrl,iDownloadSize);
                        }
                    else
                        {
                        HTTPPostL(iSecondUrl,*DataSecondPost);
                        }
                    break;
                    }
                }
            
            iObserver->HandleWebData(dataChunk);            
            body->ReleaseData();
            
            iDownloadSize += DataLength;
            StartTimer(30);//30s超时
            
            RLog::LogPoor(_L("Exit EGotResponseBodyData"));
            }
            break;

        case THTTPEvent::EResponseComplete:
            {
            //响应服务器完成
            RLog::LogPoor(_L("EResponseComplete"));
            }
            break;

        case THTTPEvent::ESucceeded:
            {
            //整个事物成功处理
            RLog::LogPoor(_L("ESucceeded"));
            RLog::LogPoor(_L("iDownloadSize = "),iDownloadSize);
            
            if(iDownloadSize < iFileLength - 1)
                {
                aTransaction.Close();
                StartGetClient(iSecondUrl,iDownloadSize);
                break;
                }
            // Transaction can be closed now. It's not needed anymore.
            aTransaction.Close();
            
            StopTimer();
            iObserver->HandleWebDataCompleteL();
            bIsReciveData = ETrue;
            iRunning = EFalse;
            }
            break;

        case THTTPEvent::EFailed:
            {
            //异常出现
            RLog::LogPoor(_L("EFailed"));
            aTransaction.Close();
            StopTimer();
            iObserver->HandleError();
            iRunning = EFalse;
            iDownloadSize = 0;
            }
            break;

        default:
            {
            TInt err = aEvent.iStatus;
            RLog::LogPoor(_L("err = "),err);
            if (aEvent.iStatus < 0)
                {
                aTransaction.Close();
                StopTimer();
                iObserver->HandleError();
                iRunning = EFalse;
                }
            }
            break;
        }
    }

经过上述处理就可以完成整个下载流程了.

以上代码适合SYMBIAN 2nd,3rd,5th三个平台通用.
  评论这张
 
阅读(722)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018