如何在Symbian中使用Http上传大文件(转帖)

    技术2025-10-09  39

    http://blog.csdn.net/chuckGao/archive/2010/08/03/5785261.aspx

     

     

    最近因为项目的关系,研究了一下在 Symbian 中使用 Http 协议上传 multipart/form-data 格式数据的实现方法。由于要求上传的数据较大,所以研究了如何在 Nokia Http Exmaple 的基础上,使用 MHTTPDataSupplier 派生类分包上传的实现。

     

    1. 在实现 Http 协议的类中(以 HttpEngine 为例),需要重写下面几个函数:

    void SetupConnectionL();

    void IssueHTTPGetL();

    void IssueHTTPPostL();

    void IssueHTTPDeleteL();

    void CancelTransaction();

    // 上传大文件时,需要特别关注下面 4 个类

    void ReleaseData();

    TBool GetNextDataPart(TPtrC8& aDataPart);

    TInt Reset();

    TInt OverallDataSize();

    在搭建初步的 HttpEngine 框架时,可以根据需求,重写 SetupConnectionL() 及 Get 、 Post 、 Delete 等函数,具体的实现方法可参考 Http 协议完成。

    2.Nokia Http Exmaple 适用的情况为一个 Chunk Post 的时候,如果想要上传较大的文件,需要重写上面 4 个类的实现。下面是 Http Engine 的简要工作流程:

    A.       通过 OverallDataSize 函数获得上传文件的总大小,这意味着,是整个上传文件的长度,而不是每次分包上传的长度。如果 Size 错误或者 Size 大小不确定,都会引起错误。

     

    B.       开始上传,将会调用 GetNextDataPart(TPtrC8& aDataPart) 得到本次上传的数据。如果是分包上传,这里是当前上传包的数据内容

     

    C.       如果上传过程中出错,将会返回,并重新调用 A 。如果成功,将会 ReleaseData(); 并根据 GetNextDataPart 之前的返回值判断是否还需要调用 GetNextDataPart 。在 C 中存在很关键的一环,如果发送过程中底层出错,将会重新通过 OverallDataSize 获得上传的总大小,而进入 OverallDataSize 就表示一切操作重头再来了,所以需要在 OverallDataSize 里面重置所有的数据指针,而一般的方法通过 Reset 将数据指针指向第一块数据。如果是使用状态机的方式进行数据传送,则需要将状态置为最先一步操作的状态。

     

     

    D.       每次数据传送完成,需要调用 ReleaseData() 释放之前发送的数据。在分包传输时,如果数据没有传完,需要显示调用 RHTTPTransaction 的 NotifyNewRequestBodyPartL() 函数通知 Engine 。不然,不会进入到 GetNextDataPart

     

    3. 对于 multipart 类型数据的上传,推荐采用状态机的方式。在每个状态中上传不同 bounary 的数据。对于上传大文件,也尽量控制分包大小在 100k 以内,以免内存分配不够而引发错误

     

    下面是一些实现代码,有些具体的操作放在了 observer 里面进行

    TBool CHttpEngine::GetNextDataPart ( TPtrC8 & aDataPart)

         {

          return iObserver .GetNextDataPart(aDataPart);

         }

    void CHttpEngine::ReleaseData ()

         {

         if ( iObserver .BytesTransfered() != iOverDataSize )        

              iTransaction . NotifyNewRequestBodyPartL ();

     

         iObserver .ReleaseData();

         }

    TInt CHttpEngine::Reset ()

         {

         //Reset the state

         iObserver .Reset();

         return KErrNone;

         }

    TInt CHttpEngine::OverallDataSize ()

         {

         Reset();

         iOverDataSize = iObserver .OverallDataSize();

         if (0 != iOverDataSize )

              return iOverDataSize ;

         return KErrNotFound;

         }

    最新回复(0)