因为工作上的需求要用到异步下载文件并解压使用,在网上找了一部分资料,发现好多都是零碎的,所以我在这里做个整合。(51开源时代)

首先还是要感谢 @iuoon 大佬提供的CurlDown源码和 @zsifz 大佬提供的zip解压源码,我对源码进行了一些删除和修改,如果有需要的可以拿去用,如果有什么修改不足的地方请见谅,这个修改的版本只是适用于我的功能需求。废话不多说,下面上代码:

我使用的cocos2dx版本为3.13

CurlDown.h

#pragma once
#ifndef __download__CurlDown__
#define __download__CurlDown__
#include <string>
#include "cocos2d.h"
#include <thread>#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
#include "../../cocos2d-x/external/curl/include/win32/curl/curl.h"
#pragma comment(lib, "libcurl_imp.lib")
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "../../cocos2d-x/external/curl/include/android/curl/curl.h"
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
#include "../../cocos2d-x/external/curl/include/ios/curl/curl.h"
#endifusing namespace std;
USING_NS_CC;/************************************************************************/
/* libcurl download file                                                */
/************************************************************************/
class CurlDown
{
public:CurlDown();~CurlDown();//入口函数void downStart();//下载控制void downloadControler();//下载bool download();//设置文件信息void setFileInfo(string filePath, string fileName, string downloadUrl);//得到下载进度double getFileDownPercent();//是否下载完成bool isDownLoadFinish();//进度回调void onProgress(double percent/*, string totalSize, string downSize,string speed*/);//下载成功回调void onSuccess(bool isSuccess);//加载zipbool loadZIP(const std::string &zipFilename, const std::string &password/*""*/);//解压zipbool unCompress(const char * pOutFileName, const std::string &password);
public:string mFilePath; // 本地存储地址string mDownloadUrl; // 下载URLstring mFileName; // 下载文件名称CURL *libcurl;double mFileDownPercent;//下载文件进度bool m_iFinishState;        //是否下载完成
};#endif

CurlDown.cpp

#include "CurlDown.h"
#include "unzip/unzip.h"
#include "cocos/platform/CCFileUtils.h"#define MAX_FILENAME 512
#define BUFFER_SIZE 128CurlDown::CurlDown()
:m_iFinishState(false),
mFileDownPercent(0)
{
}CurlDown::~CurlDown()
{}void CurlDown::setFileInfo(string filePath, string fileName, string downloadUrl)
{mFilePath = filePath;mFileName = fileName;mDownloadUrl = downloadUrl;
}static size_t write_func(void *ptr, size_t size, size_t nmemb, void *userdata) {FILE *fp = (FILE*)userdata;size_t written = fwrite(ptr, size, nmemb, fp);return written;
}/************************************************************************/
/*
这个回调函数可以告诉我们有多少数据需要传输以及传输了多少数据,单位是字节。
totalToDownload是需要下载的总字节数(这里不包括本地已下载的一部分),nowDownloaded是已经下载的字节数(指的是totalToDownload中已下载多少)。
totalToUpLoad是将要上传的字节数,nowUpLoaded是已经上传的字节数。如果你仅仅下载数据的话,那么ultotal,ulnow将会是0,反之,
如果你仅仅上传的话,那么dltotal和dlnow也会是0。clientp为用户自定义参数,
通过设置CURLOPT_XFERINFODATA属性来传递。此函数返回非0值将会中断传输,错误代码是CURLE_ABORTED_BY_CALLBACK
*/
/************************************************************************/
static int progress_func(void *ptr, double totalToDownload, double nowDownloaded, double totalToUpLoad, double nowUpLoaded)
{if (totalToDownload <= 0.000001){return 0;}CurlDown* tmpAssets = (CurlDown*)ptr;if (tmpAssets){int tmp = (int)(nowDownloaded / totalToDownload * 100);tmpAssets->onProgress(tmp);}return 0;}void CurlDown::downStart()
{m_iFinishState = 0;mFileDownPercent = 0;thread _st_d(&CurlDown::downloadControler, this);//创建一个分支线程_st_d.detach();
}void CurlDown::downloadControler()
{bool ret = false;ret = download(); //直接下载log("----ret--------->%d",ret);if (ret){       onSuccess(ret);}
}bool CurlDown::download()
{FILE *fp = NULL;fp = fopen(mFilePath.c_str(), "wb");if (fp == NULL) {// 如果文件初始化失败进行返回return false;}CURL *handle = curl_easy_init();libcurl = handle;curl_easy_setopt(handle, CURLOPT_URL, mDownloadUrl.c_str()); curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_func);        //写文件回调方法curl_easy_setopt(handle, CURLOPT_WRITEDATA, fp);                    // 写入文件对象curl_easy_setopt(handle, CURLOPT_NOPROGRESS, 0);curl_easy_setopt(handle, CURLOPT_PROGRESSFUNCTION, progress_func);  //下载进度回调方法curl_easy_setopt(handle, CURLOPT_PROGRESSDATA, this);               // 传入本类对象curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1L);                     //屏蔽其它信号curl_easy_setopt(handle, CURLOPT_LOW_SPEED_LIMIT, 1L);               //控制传送字节curl_easy_setopt(handle, CURLOPT_LOW_SPEED_TIME, 15);               //控制多少秒传送CURLOPT_LOW_SPEED_LIMITcurl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1);                //设置支持302重定向curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT, 15);               //设置下载时间,超过时间断开下载,测试模式下把这行注释可以无时间限制下载CURLcode res = curl_easy_perform(handle);//下载结果if (res == CURLE_OK){long retcode = 0;res = curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &retcode);if (!(res == CURLE_OK && retcode == 200)){CCLOG("downfile-http-faild res:%d code:%ld", res, retcode);m_iFinishState = 2;res = CURL_LAST;}}else{CCLOG("downfile-curl_easy_perform-faild res:%d", res);m_iFinishState = 2;}fclose(fp);return res == CURLE_OK;
}void CurlDown::onProgress(double percent/*, string totalSize, string downSize, string speed*/)
{mFileDownPercent = percent;
}void CurlDown::onSuccess(bool isSuccess)
{m_iFinishState = isSuccess;
}//是否下载完成
bool CurlDown::isDownLoadFinish()
{return m_iFinishState;
}//得到下载进度
double CurlDown::getFileDownPercent()
{return mFileDownPercent;
}bool CurlDown::loadZIP(const std::string &zipFilename, const std::string &password/*""*/)
{std::string filename = zipFilename;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)std::string dataFilePath = filename;
#endif#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)std::string dataFilePath = FileUtils::getInstance()->getWritablePath() + filename;if (access(dataFilePath.c_str(), 0) != 0){std::string strPath = FileUtils::getInstance()->fullPathForFilename(filename);ssize_t len = 0;unsigned char *data = 0;CCLOG("strPath:%s", strPath.c_str());data = FileUtils::getInstance()->getFileData(strPath.c_str(), "r", &len);CCLOG("file:%s, len:%zd", dataFilePath.c_str(), len);FILE* fp = fopen(dataFilePath.c_str(), "w+");if (!fp){CCLOG("file not found!");}fwrite(data, sizeof(char), len, fp);fclose(fp);delete[]data;data = 0;}
#endif//解压return unCompress(dataFilePath.c_str(), password);//return true;
}bool CurlDown::unCompress(const char * pOutFileName, const std::string &password)
{if (!pOutFileName) {CCLOG("unCompress() - invalid arguments");return 0;}FileUtils *utils = FileUtils::getInstance();std::string outFileName = utils->fullPathForFilename(pOutFileName);// 打开压缩文件unzFile zipfile = unzOpen(outFileName.c_str());if (!zipfile){CCLOG("can not open downloaded zip file %s", outFileName.c_str());return false;}// 获取zip文件信息unz_global_info global_info;if (unzGetGlobalInfo(zipfile, &global_info) != UNZ_OK){CCLOG("can not read file global info of %s", outFileName.c_str());unzClose(zipfile);return false;}// 临时缓存,用于从zip中读取数据,然后将数据给解压后的文件char readBuffer[BUFFER_SIZE];//开始解压缩CCLOG("start uncompressing");//根据自己压缩方式修改文件夹的创建方式std::string storageDir;int pos = outFileName.find_last_of("/");storageDir = outFileName.substr(0, pos);//    FileUtils::getInstance()->createDirectory(storageDir);// 循环提取压缩包内文件// global_info.number_entry为压缩包内文件个数uLong i;for (i = 0; i < global_info.number_entry; ++i){// 获取压缩包内的文件名unz_file_info fileInfo;char fileName[MAX_FILENAME];if (unzGetCurrentFileInfo(zipfile,&fileInfo,fileName,MAX_FILENAME,NULL,0,NULL,0) != UNZ_OK){CCLOG("can not read file info");unzClose(zipfile);return false;}//该文件存放路径std::string fullPath = storageDir + "/" + fileName;// 检测路径是文件夹还是文件const size_t filenameLength = strlen(fileName);if (fileName[filenameLength - 1] == '/'){// 该文件是一个文件夹,那么就创建它if (!FileUtils::getInstance()->createDirectory(fullPath.c_str())){CCLOG("can not create directory %s", fullPath.c_str());unzClose(zipfile);return false;}}else{// 该文件是一个文件,那么就提取创建它if (password.empty()){if (unzOpenCurrentFile(zipfile) != UNZ_OK){CCLOG("can not open file %s", fileName);unzClose(zipfile);return false;}}else{if (unzOpenCurrentFilePassword(zipfile, password.c_str()) != UNZ_OK){CCLOG("can not open file %s", fileName);unzClose(zipfile);return false;}}// 创建目标文件FILE *out = fopen(fullPath.c_str(), "wb");if (!out){CCLOG("can not open destination file %s", fullPath.c_str());unzCloseCurrentFile(zipfile);unzClose(zipfile);return false;}// 将压缩文件内容写入目标文件int error = UNZ_OK;do{error = unzReadCurrentFile(zipfile, readBuffer, BUFFER_SIZE);if (error < 0){CCLOG("can not read zip file %s, error code is %d", fileName, error);unzCloseCurrentFile(zipfile);unzClose(zipfile);return false;}if (error > 0){fwrite(readBuffer, error, 1, out);}} while (error > 0);fclose(out);}//关闭当前被解压缩的文件unzCloseCurrentFile(zipfile);// 如果zip内还有其他文件,则将当前文件指定为下一个待解压的文件if ((i + 1) < global_info.number_entry){if (unzGoToNextFile(zipfile) != UNZ_OK){CCLOG("can not read next file");unzClose(zipfile);return false;}}}//压缩完毕CCLOG("end uncompressing");//压缩完毕删除zip文件,删除前要先关闭unzClose(zipfile);if (remove(outFileName.c_str()) != 0){CCLOG("can not remove downloaded zip file %s", outFileName.c_str());}return true;
}

因为我的需求是lua层使用,所以需要注册到lua层,我使用的方法是使用tolua++编译pkg文件生成自定义类,然后让lua脚本使用,本来想直接用cocos2dx自带的tolua++注册到lua的,结果搞了半天,都没有成功,索性就直接用pkg的方式做了。

需要tolua++工具的童鞋自行下载:tolua++编译pkg脚本工具及CurlDown源码下载

Cocos2dx-Lua 使用Curl下载zip压缩文件并解压相关推荐

  1. Zip压缩文件没有解压密码怎么办?

    Zip压缩文件没有解压密码怎么办? 在平时,我们难免的需要到浏览器上面寻找一些需要的资源,可往往下载好了zip文件后,解压时却需要密码.真的让人很痛苦.那有没有什么办法可以破解zip解压时需要的密码呢 ...

  2. java 上传zip压缩文件并且解压

    public void parseAndAdd(MultipartFile zipFile) {//C:\Users\登录用户~1\AppData\Local\Temp\String pathName ...

  3. Android--下载zip压缩文件并解压

    网上有很多介绍下载文件或者解压zip文件的文章,但是两者结合的不多,在此记录一下下载zip文件并直接解压的方法,直接上代码. 源码下载:http://download.csdn.net/detail/ ...

  4. java解压zip_Java实现zip压缩文件的解压

    需求描述: 前段时间写了一篇博客<Java实现对文本文件MD5加密并ftp传送到远程主机目录>,实现了一部分的业务需求.然而有些业务可能不止传送一个文件,有时候客户需要传多个文件,原有系统 ...

  5. 最近很火的在线文件预览txt、doc、ppt、pdf、excel、jpg、png、zip、tar.gz等各种文件及压缩文件在线解压和预览,包括前后端设计和源码,编写搜索引擎多关键词检索名称和内容(四)

    最近很火的在线文件预览txt.doc.ppt.pdf.excel.jpg.mp4.png.zip.tar.gz等各种文件及压缩文件在线解压和预览,包括前后端设计和源码,编写一个文件搜索引擎实现多关键词 ...

  6. 最近很火的在线文件预览txt、doc、ppt、pdf、excel、jpg、png、zip、tar.gz等各种文件及压缩文件在线解压和预览,包括前后端设计和源码,编写搜索引擎多关键词检索名称和内容(五)

    最近很火的在线文件预览txt.doc.ppt.pdf.excel.jpg.mp4.png.zip.tar.gz等各种文件及压缩文件在线解压和预览,包括前后端设计和源码,编写一个文件搜索引擎实现多关键词 ...

  7. linux下tar gz bz2 tgz z等众多压缩文件的解压方法

    对于刚刚接触Linux的人来说,一定会给Linux下一大堆各式各样的文件名给搞晕.别个不说,单单就压缩文件为例,我们知道在Windows下最常见 的压缩文件就只有两种,一是,zip,另一个是.rar. ...

  8. linux解压文件卡住,Linux系统下常见的压缩文件及解压方法

    如果tar不支持j这个参数就先用 bzip2 -d xxx.tar.bz2 把它解压成.tar文件,然后再用 tar xvf xxx.tar 拆包. 压缩解压 linux下怎么解后缀名是gzip的文件 ...

  9. java上传rar文件_java实现上传zip/rar压缩文件,自动解压

    在pom中添加解压jar依赖 4.0.0 org.springframework.boot spring-boot-starter-parent 2.1.2.RELEASE com.hf uncomp ...

最新文章

  1. spring28: aspectJ--基于xml
  2. 【运营】如何有效率的进行“用户访谈”
  3. boost原理与sklearn源码_机器学习sklearn系列之决策树
  4. DJL | DJL 如何正确打开 [ 深度学习 ]
  5. 百度编辑器ueditor 字符限制
  6. 株洲市码高机器人编程_码高机器人教育
  7. 【渝粤教育】电大中专电商运营实操 (7)作业 题库
  8. POJ 3250:Bad Hair Day 好玩的单调栈
  9. mac 安装pip教程
  10. verilog 产生m序列
  11. 既能被2又能被5整C语言,2012年国研究生统一考试心理学专业试题与答案
  12. 21张手机壁纸,送给我爱的你们~
  13. 业绩堪忧,上市曲折,友宝梦醒港股?
  14. 多路输出开关电源的设计及应用原则
  15. 泛泰A880 Recovery
  16. 相似图片搜索的原理(1)
  17. SCI回复审稿意见的模板
  18. 大学生创新创业大赛应该如何入手?互联网+ 三创赛 挑战杯 有现成模板
  19. 南京大学计算机科学系杨献春,关于成立新一届江苏省青少年信息学奥林匹克竞赛委员会的通知...
  20. 用Python实现tree命令

热门文章

  1. 怎么使用云服务器创建一个网页
  2. 不良资产评估方法改进研究
  3. 【技术新趋势】合合信息:文本纠错提升OCR任务准确率的方法
  4. Python限定参数类型
  5. 什么是线下门店陈列洞察?百度AI人工智能
  6. STC15W408AS单片机通过ADC端口采集模拟量并从串口打印数值
  7. 在JDK和Eclipse下Java Applet的编写和运行方式
  8. PHP输出星座,[转]一个最简的js和php通过月日获取星座的代码
  9. 河南工程学院计算机网络试卷,河南工程学院计算机网络课程设计讲述.doc
  10. 如何根据波动率曲面设计策略