使用libcurl下载网络数据存储到数据库(使用libcurl和sqlite数据库)


     以前一直看别人的帖子,这次自己也是通过别人的帖子解决了问题,质量略低,只是希望能够给别人一些方便,不要再走一些冤枉路。

一 废话不多说,首先需要进行的就是编译库,首先从sqlite开始,

Sqlite的配置:(参照http://blog.csdn.net/zmb2011/article/details/6401104

1. 首先从SQLite的官网http://www.sqlite.org/download.html上下载两个文件包:sqlite-amalgamation-3070602.zipsqlite-dll-win32-x86-3070600.zip

2. 解压amalgamation文件(里面包括四个文件,主要的是sqlite3.h)到D:/SQLite3/include,解压dll文件(sqlite3.defsqlite3.dll文件)到D:/SQLite3/lib

3. VS2010的安装文件夹中的Visual Studio 10/VC/bin中找到LIB.exeLink.exe,从Visual Studio 10中搜索得到mspdb100.dll文件,放入到D:/SQLite3/lib

4. 打开cmd窗口,转到D:/SQLite3/lib目录下,输入命令:LIB /DEF:sqlite3.def /machine:IX86,则会产生lib文件

5. 配置VS2010VC++目录和库目录,分别包含includelib文件夹

然后是libcurl的配置:

Libcurl的配置比较简单,只需要找到工程文件,将工程文件打开运行,就可以了,详细的中间有些小问题,都是可以解决的,如果遇到生成中缺少DLL的话,可以去网上下载一个,只要版本对就行,版本不对应该也没有问题。

废话不多说上代码:

可以下载到本地数据库的方法:

#include <stdio.h>

#include <curl/curl.h> 

#include<string>

#include<sqlite3.h>

#include<iostream>

#include<fstream>

#include<vector>

#include<Windows.h>

using namespace std;

  size_t write_data(FILE *ptr, size_t size, size_t count,FILE *stream)

   {

    FILE*fp=(FILE*)stream;

size_t return_size=fwrite(ptr,size,count,fp);

return return_size;

 }

 

 int main()

   {

           CURLcode res;

           res = curl_global_init(CURL_GLOBAL_WIN32);

           CURL *curl_handle; 

           curl_handle = curl_easy_init();

           char *zErrMsg = 0;

   if(res!=CURLE_OK)

   {

             std::cerr<<"initialize libcurl failed";

   return-1;

   }

 if(curl_handle!=NULL)

 {   

 FILE *fp = fopen("d:/ceshi/download.jpg","wb+");

                 res = curl_easy_setopt(curl_handle, CURLOPT_URL, "http://travel.paintedstork.com/blog/wp-content/uploads/2012/10/2013-calendar-images-1.jpg" );

                 res = curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);

                 res = curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, fp);

                 res = curl_easy_perform(curl_handle); 

            sqlite3 *db; 

   sqlite3_stmt *stat;

   char *ffile;

       int value= sqlite3_open("d:/ceshi/gtestpic.db", &db);

                   sqlite3_exec(db, "CREATE TABLE list (fliename varchar(128) UNIQUE, fzip blob);", 0, 0, &zErrMsg);

       sqlite3_prepare(db, "insert into list values ('download',?);", -1, &stat, 0);

   long filesize = 0;

                   fseek(fp, 0, SEEK_END);

                   filesize = ftell(fp);

                   fseek(fp, 0, SEEK_SET);

  ffile=new char[filesize+1];

  size_t sz=fread(ffile,sizeof(char),filesize+1,fp);

  fclose(fp);

   sqlite3_bind_blob(stat,1,ffile,filesize, NULL);

                   sqlite3_step(stat);    

  delete(ffile);

  sqlite3_finalize(stat);

  sqlite3_close(db);

 

 fclose(fp) ; 

 curl_easy_cleanup(curl_handle);

 curl_global_cleanup();

 }

   system("ERASE d:\\ceshi\\download.jpg");

   return 0;

 }

基本思路是这样的,先在本地建立文件,在通过libcurl的一系列函数进行加载,在这里libcurl的函数都是指定的,当然libcurl的函数有很多,我们不需要都理解,用到什么可以直接找,具体的每条函数有什么用我就不详细赘述了,大家可以参考这篇博文,http://blog.sina.com.cn/s/blog_40ce02d70100pt43.html讲的非常详细,可以有选择的参考,我重点要说的是第二种方法,本人系初入研究生一枚,水平有限,研究第二种方法迟迟没有进展,幸得师姐相助,半天搞定,部分代码参考网络,上代码

// scurl.cpp : 定义控制台应用程序的入口点。

//

#include <stdio.h>

#include <curl/curl.h> 

#include<string>

#include<sqlite3.h>

#include<iostream>

#include<fstream>

#include<vector>

#include<Windows.h>

using namespace std;

//写入函数  

 

static char errorBuffer[CURL_ERROR_SIZE];

static int writer(char*, size_t,size_t,string*);

static bool init(CURL *&, char *, string *);

static size_t get_count(char *url){

CURL *curl;

CURLcode res;

 

double filesize=0;

 

curl = curl_easy_init();

if (curl) {

res=curl_easy_setopt(curl, CURLOPT_URL, url);

res=curl_easy_setopt(curl, CURLOPT_NOBODY,1L);

 

res=curl_easy_setopt(curl, CURLOPT_HEADER, 0L);

 

res=curl_easy_perform(curl);

 

if (res == CURLE_OK) {

res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &filesize);

} else {

filesize = -1;

}

return filesize;

}

}

int main()

{

char *zErrMsg = 0;

size_t fsize=0;

CURL *conn = NULL;

CURLcode code;

string buffer;

curl_global_init(CURL_GLOBAL_ALL);

char* url = "http://travel.paintedstork.com/blog/wp-content/uploads/2012/10/2013-calendar-images-1.jpg";

 

fsize=get_count(url);

 

if (!init(conn,url,&buffer))

{

fprintf(stderr,"Connection initializion failed\n");

exit(EXIT_FAILURE);

}

 

code = curl_easy_perform(conn);

if (code != CURLE_OK)

{

fprintf(stderr, "Failed to get '%s' [%s]\n", url, errorBuffer);

exit(EXIT_FAILURE);

}

curl_easy_cleanup(conn);

printf("%s\n",buffer.c_str());

 

FILE *file;

file = fopen("d:/resultlib.jpg", "wb");

if(file != NULL)

{

size_t ret = fwrite((void*)buffer.c_str(), sizeof(char), fsize,file);

fclose(file);

}

 

 

//读入数据库  

sqlite3 *db; 

sqlite3_stmt *stat;

int value= sqlite3_open("d:/gtestpic.db", &db);

sqlite3_exec(db, "CREATE TABLE list (fliename varchar(128) UNIQUE, fzip blob);", 0, 0, &zErrMsg);

sqlite3_prepare(db, "insert into list values ('download3',?2);", -1, &stat, 0);

sqlite3_bind_blob(stat,2,(void*)buffer.c_str(),fsize, SQLITE_STATIC);

sqlite3_step(stat);

 

//选取该条数据

sqlite3_prepare(db, "select*from list;", -1, &stat, 0);

sqlite3_step(stat);

//得到记录中的BLOB字段

const void * test = sqlite3_column_blob(stat, 1);

//得到字段中数据的长度

int size = sqlite3_column_bytes(stat, 1);

 

FILE *fp2;

fp2 = fopen("d:/outfile2.jpg", "wb");

if(fp2 != NULL)

{

size_t ret = fwrite(test, sizeof(char), size, fp2);

fclose(fp2);

}

//释放资源

//delete[]buffer;

sqlite3_finalize(stat);

sqlite3_close(db);

//} 

 

//释放资源

 

//curl_easy_cleanup(curl_handle);

curl_global_cleanup();

 

 

return 0;

}

 

static bool init(CURL *&conn, char *url, string *p_buffer)

{

CURLcode code;

conn = curl_easy_init();

if (conn == NULL)

{

fprintf(stderr,"Failed to create CURL connection\n");

exit(EXIT_FAILURE);

}

code = curl_easy_setopt(conn,CURLOPT_ERRORBUFFER,errorBuffer);

if (code!=CURLE_OK)

{

fprintf(stderr,"Failed to set error buffer[%d]\n",code);

return false;

}

 

code = curl_easy_setopt(conn,CURLOPT_URL,url);

if (code!=CURLE_OK)

{

fprintf(stderr,"Failed to set URL [%s]\n",errorBuffer);

return false;

}

 

code = curl_easy_setopt(conn, CURLOPT_FOLLOWLOCATION, 1);

if (code != CURLE_OK)

{

fprintf(stderr, "Failed to set redirect option [%s]\n", errorBuffer);

return false;

}

 

code = curl_easy_setopt(conn,CURLOPT_WRITEFUNCTION,writer);

if (code != CURLE_OK)

{

fprintf(stderr, "Failed to set writer [%s]\n", errorBuffer);

return false;

}

 

code = curl_easy_setopt(conn, CURLOPT_WRITEDATA, p_buffer);

if (code != CURLE_OK)

{

fprintf(stderr, "Failed to set write data [%s]\n", errorBuffer);

return false;

}

return true;

 

}

 

static int writer(char* data,size_t size,size_t nmemb, string *writerData)

{

unsigned long sizes = size*nmemb;

if(writerData == NULL)

return 0;

writerData->append(data, sizes);

return sizes;

}

大致思路是这样的,利用函数get_count()获取目标文件的大小,在新开辟内存,大小为目标文件的大小,这样利用libcurl函数将目标文件存入字符数组,存入后就可以导入数据库了,最后一段代码是用来进行读数据读取的。

    在过程中遇到了不少的问题,一开始并不知道libcurl中有可以用来读取目标文件的大小的函数,但是后来发现了函数CURLINFO_CONTENT_LENGTH_DOWNLOAD才找打了解决问题的正确思路,另外在write_data中开始时用的是memcpy函数,但是后来证明这个函数在这方面有问题,具体问题现在也没有搞清楚,改为memmove后,问题还是没有实质性的进展,后来被师姐将数据流改为string格式,使用append函数,才解决了问题,有时候觉得自己一个人解决了很就解决不了的问题,别人只要稍微指点就解决了,不由的觉得自己太水了,以后还要继续努力。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值