Beispiel #1
0
    // 功能:通知文件下载事件
    void  NotifyDownEvent(string url, bool bSuc, DownResFile resInfo)
    {
        // 这里只是输出一个日志,用户自行扩展事件吧
        MemBlock pBlock = new MemBlock();

        pBlock.resFile = resInfo;
        PushWrite(pBlock); // 通知写线程关闭对应的文件

        if (bSuc)
        {
            Debug.Log("文件下载成功,url:" + url);
        }
        else
        {
            Debug.LogError("文件下载失败,url:" + url);
        }
    }
Beispiel #2
0
    void  WriteBlock(MemBlock pBlock)
    {
        // 这里可以使用一个特殊的标记,表示文件下载完成的
        if (pBlock.data == null)
        {
            // 在这里添加事件处理
            if (pBlock.resFile != null)
            {
                if (pBlock.resFile.file != null)
                {
                    pBlock.resFile.file.Close();
                    pBlock.resFile.file = null;
                }
                pBlock.resFile = null;
            }
            return;
        }
        // 必要的话,在这里记录一下下载的状态, 这个用户自行扩展吧
        DownResFile resFile = pBlock.resFile;

        if (resFile.file == null)
        {
            string szLocalPathName = GetLocalPathNameByUrl(pBlock.url);
            if (pBlock.nFileOfset == 0)
            {
                if (File.Exists(szLocalPathName))
                {
                    File.Delete(szLocalPathName);
                }
            }
            resFile.file = new FileStream(szLocalPathName, FileMode.OpenOrCreate, FileAccess.Write);
            if (resFile.file == null)
            {
                Debug.LogError(szLocalPathName + "文件打开失败!");
            }
        }
        FileStream file = resFile.file;

        if (file != null)
        {
            file.Seek(pBlock.nFileOfset, SeekOrigin.Begin);
            file.Write(pBlock.data, 0, pBlock.nDownSize);
            file.Flush();
        }
    }
Beispiel #3
0
    void DownFile(CHttp http, string url, int nFileSize, int nLastDownSize)
    {
        // 如果文件比较小的话,可以不分片下载,真正下载整个文件
        if (nFileSize == 0)
        {
            CHttpDown.GetDownFileSize(url, out nFileSize);
        }

        DownResFile resInfo = new DownResFile();

        resInfo.url       = url;
        resInfo.nFileSize = 0;

        if (0 == nFileSize)
        {
            // 无法获取文件大小信息,整个下载吧
            bool bSuc = DownPart(http, url, 0, 0, nFileSize, resInfo);
            NotifyDownEvent(url, bSuc, resInfo);
            return;
        }
        int nPageSize   = 1024 * 300;    // 分片的大小,应小于你的最大限制下载速度, 这里默认选用300K,读者自己根据项目修改
        int nFileOffset = nLastDownSize; // 从上一次下载的位置接着下载
        int nDownSize   = 0;

        for (; nFileOffset < nFileSize; nFileOffset += nPageSize)
        {
            // 先限速
            LimitSpeed();
            // 开始分片下载
            nDownSize = nFileOffset + nPageSize < nFileSize ? nPageSize : (nFileSize - nFileOffset);
            if (!DownPart(http, url, nFileOffset, nDownSize, nFileSize, resInfo))
            {
                NotifyDownEvent(url, false, resInfo);
                return;
            }
        }
        NotifyDownEvent(url, true, resInfo);
    }
Beispiel #4
0
    bool DownPart(CHttp http, string url, int nFileOffset, int nDownSize, int nFileSize, DownResFile resFile)
    {
        // 调用Http下载的代码
        nDownSize = http.PrepareDown(url, nFileOffset, nDownSize, nDownSize == 0);
        if (nDownSize <= 0)
        {
            Debug.LogError("文件下载失败,url:" + url + "(" + nFileOffset + "-" + nDownSize + ")");
            return(false);
        }

        // 将下载的内容提交到写线程
        byte[] szTempBuf    = null;
        int    nCurDownSize = 0;
        int    nRecTotal    = 0;
        int    nRecLen      = 0;
        int    nOffset      = 0;

        nCurDownSize = nDownSize > 4096 ? 4096 : nDownSize;
        MemBlock pBlock = AllockBlock(url, nFileOffset, nCurDownSize, nFileSize);  // 从内存池中取一个4K的内存片

        while (nDownSize > 0 && !m_bNeedStop)
        {
            // 必要的话,在这里添加限速功能或限制接收速度的功能,以免网速太快,导致一秒内分配太多内存
            //LimitSpeed();
            nRecLen = http.FastReceiveMax(ref szTempBuf, ref nOffset, 4096 - nRecTotal);
            if (nRecLen > 0)
            {
                OnReceive(nRecLen);  // 统计下载的流量
                Array.Copy(szTempBuf, nOffset, pBlock.data, nRecTotal, nRecLen);
                nRecTotal += nRecLen;
                // 如果当前块接收满了
                if (nRecTotal >= nCurDownSize)
                {
                    pBlock.resFile = resFile;
                    PushWrite(pBlock);// 提交写文件
                    nRecTotal    = 0;
                    nDownSize   -= nCurDownSize;
                    nFileOffset += nCurDownSize;
                    nCurDownSize = nDownSize > 4096 ? 4096 : nDownSize;
                    // 必要的话,加上限额等待
                    if (nCurDownSize > 0)
                    {
                        WaitBlock(1024 * 1024);                                          // 检测当前内存池分配的总量,超过就挂起
                        pBlock = AllockBlock(url, nFileOffset, nCurDownSize, nFileSize); // 从内存池中取一个4K的内存片
                    }
                }
            }
            else
            {
                return(false); // 文件读取失败,可能是网络出问题了
            }
        }
        return(true);
    }