1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include "Base.h"
#include <sys/stat.h>
#include "curl/curl.h"
#include "curl/easy.h"
#include "FileDownload.h"
 
#define CHECK_CURL_ERROR(ERROR_CODE) if (ERROR_CODE != CURLE_OK){logDebug("%s, code:%d", #ERROR_CODE, int(ERROR_CODE));return;}
 
static int handleProgressUpdate(void *userData, double totalToDownload, double nowDownloaded, double totalToUpLoad, double nowUpLoaded)
{
    auto self = (FileDownload*)userData;
    if (totalToDownload > 0)
    {
        auto percent = nowDownloaded / totalToDownload * 100;
        if (percent != self->percent)
        {
            self->percent = percent;
            if (self->onDownloadUpdate)
            {
                self->onDownloadUpdate(self, nowDownloaded, totalToDownload);
            }
        }
    }
    return 0;
}
static size_t handleWirte(void *buff, size_t size, size_t nmemb, void *userData)
{
    auto self = (FileDownload*)userData;
    if (self->fileObj == nullptr)
    {
        self->checkOpenFile();
    }
    if (self->fileObj)
    {
        return fwrite(buff, size, nmemb, self->fileObj);
    }
    else
    {
        return 0;
    }
}
static size_t handleHeader(void *ptr, size_t size, size_t nmemb, void *userData)
{
    auto self = (FileDownload*)userData;
    self->checkOpenFile();
    self->errorInfo.append((const char*)ptr, size * nmemb);
    return size * nmemb;
}
static void onDownloadWin32(std::shared_ptr<FileDownload> download)
{
    auto curl = curl_easy_init();
    if (curl == nullptr)
    {
        LOG_DEBUG("%s", "curl_easy_init fail");
        return;
    }
    bool result = false;
    download->fileIndex = 0;
    while (!download->fileNameList.empty())
    {
        download->fileIndex++;
        download->curl = curl;
        auto& fileName = download->fileNameList.front();
        download->curFileName = fileName;
        download->percent = 0;
        auto fileUrl = download->url + fileName;
        auto savePath = download->saveDir + fileName;
 
        double downloadFileLenth = 0;
        long responseCode = 0;
        CURLcode ret = CURLE_OK;
        bool isExist = cocos2d::FileUtils::getInstance()->isFileExist(savePath);
        if (isExist)
        {
            auto tmpcurl = curl_easy_init();
            CHECK_CURL_ERROR(curl_easy_setopt(tmpcurl, CURLOPT_URL, fileUrl.c_str()));
            CHECK_CURL_ERROR(curl_easy_setopt(tmpcurl, CURLOPT_HTTPGET, 1));    //使用HTTPGET
            CHECK_CURL_ERROR(curl_easy_setopt(tmpcurl, CURLOPT_NOBODY, 1));    //不需求body 
            ret = curl_easy_perform(tmpcurl);
            CHECK_CURL_ERROR(curl_easy_getinfo(tmpcurl, CURLINFO_RESPONSE_CODE, &responseCode));
            if (ret == CURLE_OK && responseCode == 200)
            {
                curl_easy_getinfo(tmpcurl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &downloadFileLenth);
            }
            curl_easy_cleanup(tmpcurl);
        }
         
        struct stat info;
        curl_off_t fileSize = stat(savePath.c_str(), &info) == 0 ? info.st_size : 0;
        if (!isExist || fileSize < (int)downloadFileLenth)
        {
            CHECK_CURL_ERROR(curl_easy_setopt(curl, CURLOPT_URL, fileUrl.c_str()));
            CHECK_CURL_ERROR(curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, fileSize));
            CHECK_CURL_ERROR(curl_easy_setopt(curl, CURLOPT_WRITEDATA, download.get()));
            CHECK_CURL_ERROR(curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handleWirte));
            CHECK_CURL_ERROR(curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0));
            CHECK_CURL_ERROR(curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L));
            CHECK_CURL_ERROR(curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, download.get()));
            CHECK_CURL_ERROR(curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, handleHeader));
            CHECK_CURL_ERROR(curl_easy_setopt(curl, CURLOPT_HEADERDATA, download.get()));
            CHECK_CURL_ERROR(curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, handleProgressUpdate));
            CHECK_CURL_ERROR(curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L));
            CHECK_CURL_ERROR(curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1L));
            CHECK_CURL_ERROR(curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 5L));
            CHECK_CURL_ERROR(curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1));
            CHECK_CURL_ERROR(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0));
            CHECK_CURL_ERROR(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0));  
            ret = curl_easy_perform(curl);
            CHECK_CURL_ERROR(curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode));
        }
         
        if (download->fileObj)
        {
            fclose(download->fileObj);
            download->fileObj = nullptr;
        }
        if ((ret == CURLE_OK && responseCode >= 200 && responseCode <= 299) || (ret == CURLE_RANGE_ERROR && responseCode == 416 && fileSize > 0))
        {
            download->fileNameList.erase(download->fileNameList.begin());
            result = true;
        }
        else
        {
            result = false;
            download->errorInfo += curl_easy_strerror(ret);
            if (download->onDownloadError)
            {
                download->onDownloadError(download.get(), download->errorInfo);
            }
            LOG_DEBUG("%s", download->errorInfo.c_str());
            break;
        }
    }
    curl_easy_cleanup(curl);
    if (result)
    {
        if (download->onDownloadFinish)
        {
            download->onDownloadFinish(download.get());
        }
    }
}
 
void FileDownload::start(std::shared_ptr<FileDownload> download)
{
    if (!download->url.empty())
    {
        if (download->url.back() != '/')
        {
            download->url.push_back('/');
        }
    }
    cocos2d::FileUtils::createDirectory(download->saveDir);
    auto t = std::thread(onDownloadWin32, download);
    t.detach();
}
 
void FileDownload::checkOpenFile()
{
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);
    if ((responseCode >= 200 && responseCode <= 299) && fileObj == nullptr)
    {
        fileObj = fopen((saveDir + curFileName).c_str(), "ab+");
    }
}

  

posted @ 2023-03-17 20:37 书山有路,学海无涯 阅读(34) 评论(0) 推荐(0) 编辑
摘要: 1、先下载depot_tools git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git 2、需要vpn环境,需要vpn端口,我本机上的vpn端口是17890,在cmd命令中设置配置: git config 阅读全文
posted @ 2022-04-30 18:22 书山有路,学海无涯 阅读(539) 评论(0) 推荐(0) 编辑
摘要: 1、 安装msys2工具以及编译工具链以及cmake 2、 在github上下载openal项目openal-soft-openal-soft-1.19.0,https://github.com/kcat/openal-soft/releases 3、 解压openal项目,打开MinGW32终端进 阅读全文
posted @ 2021-01-19 11:42 书山有路,学海无涯 阅读(653) 评论(0) 推荐(0) 编辑
摘要: #ifndef _LUA_WRAPPER_ #define _LUA_WRAPPER_ extern "C" { #include "lua.h" #include "lualib.h" #include "lauxlib.h" } #include #include #include static size_t Lua_GetSize(lua_State* L, int pos) ... 阅读全文
posted @ 2018-08-17 20:03 书山有路,学海无涯 阅读(333) 评论(0) 推荐(0) 编辑
摘要: //NetworkManager.h #ifndef _NET_WORK_MANAGER_ #define _NET_WORK_MANAGER_ #include "event2/util.h" #include "event_struct.h" #include struct event_base; struct evconnlistener; struct sockaddr_in;... 阅读全文
posted @ 2018-08-17 19:38 书山有路,学海无涯 阅读(237) 评论(0) 推荐(0) 编辑
摘要: 一直想学学cocos2dx中如何使用tolua++工具使得lua脚本调用C++函数,今天就来搞一下,顺便记录下来:首先,我们打开cocos2dx-2.2.4中projects下的test的VS工程,可以看到这个例子里面已经有一个HelloWorld的类,我们就用它来说明一下。然后,我们照着Hello... 阅读全文
posted @ 2015-04-26 19:08 书山有路,学海无涯 阅读(2486) 评论(0) 推荐(0) 编辑
摘要: 最近在接触OpenGL,使用的书籍就是那本《OpenGL超级宝典》,不过编程环境的搭建和设置还是比较麻烦的,在网上找了很多资料,找不到GLTools.lib这个库。没办法自己就借助源码自己生成了:1、 准备下载的packageGlew:可以选择glew-1.12.0-win32.zip;下载地址:h... 阅读全文
posted @ 2015-03-22 22:23 书山有路,学海无涯 阅读(848) 评论(0) 推荐(0) 编辑
摘要: 快速排序、归并排序、堆排序三种排序算法的性能谁最好呢?网上查了一下说快速排序最快、其次是归并排序,最差的是堆排序;而理论上三种排序算法的时间复杂度都是O(nlogn),只不过快速排序最差的会达到O(n^2),但是数据的随机性会消除这一影响,今天就来实际比较一下: 1 #include 2 #i... 阅读全文
posted @ 2015-03-09 20:54 书山有路,学海无涯 阅读(6672) 评论(1) 推荐(0) 编辑
摘要: 今天复习了一下二叉树的前序遍历、中序遍历、后序遍历的递归与非递归算法,顺便记录一下://TreeTest.h#include struct TreeNode{ int value; TreeNode* leftChild; TreeNode* rightChild; void... 阅读全文
posted @ 2015-03-05 23:37 书山有路,学海无涯 阅读(444) 评论(0) 推荐(0) 编辑
摘要: 1、bind的工作原理 bind 并不是一个单独的类或函数,而是非常庞大的家族,依据绑定的参数的个数和要绑定的调用对象的类型,总共有数十种不同的形式,编译器会根据具体的绑定代码制动确定要使用的正确的形式,bind的基本形式如下:template bind(F f);template bind(F f... 阅读全文
posted @ 2014-09-18 14:03 书山有路,学海无涯 阅读(4463) 评论(1) 推荐(2) 编辑
点击右上角即可分享
微信分享提示