curl多线程下载实现

其实libcurl自带一个应用,很高大上,但是作为范例参考怎么使用libcurl觉得不大适合!还是写一些helloworl的程序的,一目了然......

#include "stdafx.h"
#include <io.h>
#include "curl/curl.h"
#include <string>

#include "curl/easy.h"

#include "pthread.h"

using namespace std;

struct tNode
{
 FILE *fp;
 int startidx;
 int maxidx;
 void *_curl;
 pthread_t _tid;
};
bool bError = false;
int threadCnt = 0;
static pthread_mutex_t foo_mutex = PTHREAD_MUTEX_INITIALIZER;
static size_t downLoadPackage(void *ptr, size_t size, size_t nmemb, void *userdata)
{
 tNode *node = (tNode*)userdata;
 size_t written = 0;
 pthread_mutex_lock(&foo_mutex);
 if ( node->startidx + size * nmemb <= node->maxidx )
 {
  fseek( node->fp, node->startidx, SEEK_SET );
  written = fwrite(ptr, size, nmemb, node->fp);
  node->startidx += size * nmemb;
 }
 else
 {
  fseek( node->fp, node->startidx, SEEK_SET );
  written = fwrite(ptr, 1, node->maxidx - node->startidx + 1, node->fp);
  node->startidx = node->maxidx;
 }
 pthread_mutex_unlock(&foo_mutex);
 return written;
}

int assetsManagerProgressFunc(void *ptr, double totalToDownload, double nowDownloaded, double totalToUpLoad, double nowUpLoaded)
{
 static int percent = 0;
 int tmp = 0;
 if ( totalToDownload > 0 )
 {
  tmp = (int)(nowDownloaded / totalToDownload * 100);
 }
 
 printf("下载进度%0d%%\r", tmp);
 return 0;
}

/************************************************************************/
/* 获取要下载的远程文件的大小            */
/************************************************************************/
long getDownloadFileLenth(const char *url){
 double downloadFileLenth = 0;
 CURL *handle = curl_easy_init();
 curl_easy_setopt(handle, CURLOPT_URL, url);
 curl_easy_setopt(handle, CURLOPT_HEADER, 1);    //只需要header头
 curl_easy_setopt(handle, CURLOPT_NOBODY, 1);    //不需要body
 if (curl_easy_perform(handle) == CURLE_OK)
 {
  curl_easy_getinfo(handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &downloadFileLenth);
 }
 else
 {
  downloadFileLenth = -1;
 }
 return downloadFileLenth;
}

void* workThread(void* pData)
{
 tNode* pNode = (tNode*)pData;

int res = curl_easy_perform(pNode->_curl);

if ( res != 0 )
 {

}

curl_easy_cleanup(pNode->_curl);

pthread_mutex_lock(&foo_mutex);
 threadCnt --;
 pthread_mutex_unlock(&foo_mutex);
 delete pNode;
 pthread_exit(0);

return NULL;
}

bool downLoad(int threadNum, std::string _packageUrl, std::string _storagePath, std::string fileName )
{
 long fileLength = getDownloadFileLenth(_packageUrl.c_str());

if ( fileLength <= 0 )
 {
  printf("get the file error...");
  return false;
 }


 // Create a file to save package.
 const string outFileName = _storagePath + fileName;
 FILE *fp = fopen(outFileName.c_str(), "wb");
 if (! fp)
 {
  return false;
 }

//_chsize((int)fp, fileLength);

int gap = fileLength / threadNum;

for ( int i = 0; i <= threadNum; i ++ )
 {
  tNode* pNode = new tNode();

if ( i < threadNum )
  {
   pNode->startidx = i * gap;
   pNode->maxidx = pNode->startidx - 1;
  }
  else
  {
   if ( fileLength % threadNum != 0 )
   {
    pNode->startidx = i * gap;
    pNode->maxidx = fileLength - 1;
   }
  }

CURL* _curl = curl_easy_init();

pNode->_curl = _curl;
  pNode->fp = fp;

// Download pacakge
  curl_easy_setopt(_curl, CURLOPT_URL, _packageUrl.c_str());
  curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, downLoadPackage);
  curl_easy_setopt(_curl, CURLOPT_WRITEDATA, pNode);
  curl_easy_setopt(_curl, CURLOPT_NOPROGRESS, false);
  curl_easy_setopt(_curl, CURLOPT_PROGRESSFUNCTION, assetsManagerProgressFunc);
  //curl_easy_setopt(_curl, CURLOPT_PROGRESSDATA, this);
  curl_easy_setopt(_curl, CURLOPT_NOSIGNAL, 1L);
  curl_easy_setopt(_curl, CURLOPT_LOW_SPEED_LIMIT, 1L);
  curl_easy_setopt(_curl, CURLOPT_LOW_SPEED_TIME, 5L);

pthread_mutex_lock(&foo_mutex);
  threadCnt ++;
  pthread_mutex_unlock(&foo_mutex);
  int rc = pthread_create (&pNode->_tid, NULL, workThread,pNode);
 }

if (bError)
 {
  fclose(fp);
  return false;
 }

while (threadCnt >0)
 {
  Sleep(1000);
 }

fclose(fp);

printf("download succed......\n");
 return true;
}

int _tmain(int argc, _TCHAR* argv[])
{
 downLoad(10, "http://ardownload.adobe.com/pub/adobe/reader/win/11.x/11.0.01/en_US/AdbeRdr11001_en_US.exe", "./", "AdbeRdr11001_en_US.exe");

getchar();
 return 0;
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/321831a3b966f1c04bcab8c700f84fa2.html