首页 > 其他分享 >curl的简单使用

curl的简单使用

时间:2023-03-17 20:44:31浏览次数:32  
标签:简单 CURL ERROR easy 使用 download curl CHECK

#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+");
    }
}

  

标签:简单,CURL,ERROR,easy,使用,download,curl,CHECK
From: https://www.cnblogs.com/yu-chao/p/17228105.html

相关文章

  • redis的简单动态字符串
    概念redis在c的基础上编写,但是redis的许多数据结构是不同于c的数据结构。redis的字符串表示是利用自己构建的SDS(简单动态字符串)作为默认字符串表示的。而c默认的字符......
  • Java中使用字节流和字符流操作文件的几种方法和性能对比
    注:本文转自:https://mp.weixin.qq.com/s/QuFkw-f1l0kyOqsBNNrRmw在Java中操作文件的方法本质上只有两种:字符流和字节流,而字节流和字符流的实现类又有很多,因此在文件写入......
  • 跟艾文学编程 《零基础入门学Python》Jupyter Notebook安装和使用
    作者:艾文,计算机硕士学位,企业内训讲师和金牌面试官,公司资深算法专家,现就职BAT一线大厂。 内容:跟艾文学编程《零基础入门学Python》本节内容● Jupyter扩展安装● Jup......
  • 深入理解Display类的使用
     熟悉了MIDlet类的使用以后,下面来熟悉一下Display类的使用,这个类也是进行J2ME编程中经常要使用到的类之一。      Display类有两个最主要的作用:1、 获得屏幕的属......
  • 使用Socket连接穿越CMWAP代理
    在J2ME网络程序开发过程中,为了节约用户支付的网络费用,很多J2ME手机网络程序都支持CMWAP代理。      但是由于CMWAP只是中国移动建立的一个HTTP网络服务器,所以在使用H......
  • bs4详解,css选择器,selenium基本使用,无界面浏览器,selenium其它用法
    bs4详解,css选择器,selenium基本使用,无界面浏览器,selenium其它用法bs4详解'''bs4:全称beautifulsoup4,从HTML或者HTML文件中提取数据的Python库,用来解析爬取回来的xml安......
  • 图像识别在测试中的使用
    使用场景:登录时的图像验证码APP自动化测试(Airtest)Web端UI自动化测试通过图像识别做断言 断言方法:1、大图中找小图  2、判断前后版本的页面上元素是否一致(比......
  • selenium使用
    目录selenium基本使用无界面浏览器selenium其他用法1.小案例,自动登录2.查找标签3.获取位置属性大小、文本4.等待元素被加载5.元素操作6.执行JS代码7.切换选项卡8.浏览器......
  • bs4介绍与使用,selenium基本使用
    目录beautifulsoup4(bs4)介绍与使用bs4的遍历文档树美化并查看内容获取标签获取标签名获取标签属性获取标签的内容嵌套选择就是一直点了解bs4搜索文档树字符串当条件另一种方......
  • (3) MasaFramework 入门第三篇,使用MasaFramework
    首先我们需要创建一个MasaFramework模板的项目,项目名称TokenDemo,项目类型如图所示删除Web/TokenDemo.Admin项目,新建MasaBlazorPro项目模板项目,项目位置在src/Web项目......