//采用CURLOPT_RESUME_FROM_LARGE 实现文件断点续传功能 #include <stdlib.h> #include <stdio.h> #include <sys/stat.h> #include <curl/curl.h> //这个函数为CURLOPT_HEADERFUNCTION参数构造 /* 从http头部获取文件size*/ size_t getcontentlengthfunc(void *ptr, size_t size, size_t nmemb, void *stream) { int r; long len = 0; r = sscanf(ptr, "Content-Length: %ld\n", &len); if (r) /* Microsoft: we don't read the specs */ *((long *) stream) = len; return size * nmemb; } /* 保存下载文件 */ size_t wirtefunc(void *ptr, size_t size, size_t nmemb, void *stream) { return fwrite(ptr, size, nmemb, stream); } /*读取上传文件 */ size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream) { FILE *f = stream; size_t n; if (ferror(f)) return CURL_READFUNC_ABORT; n = fread(ptr, size, nmemb, f) * size; return n; } // 下载 或者上传文件函数 int download(CURL *curlhandle, const char * remotepath, const char * localpath,long timeout, long tries) { FILE *f; curl_off_t local_file_len = -1 ; long filesize =0 ; CURLcode r = CURLE_GOT_NOTHING; int c; struct stat file_info; int use_resume = 0; /* 得到本地文件大小 */ //if(access(localpath,F_OK) ==0) if(stat(localpath, &file_info) == 0) { local_file_len = file_info.st_size; use_resume = 1; } //采用追加方式打开文件,便于实现文件断点续传工作 f = fopen(localpath, "ab+"); if (f == NULL) { perror(NULL); return 0; } //curl_easy_setopt(curlhandle, CURLOPT_UPLOAD, 1L); curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath); curl_easy_setopt(curlhandle, CURLOPT_CONNECTTIMEOUT, timeout); // 设置连接超时,单位秒 //设置http 头部处理函数 curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, getcontentlengthfunc); curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &filesize); // 设置文件续传的位置给libcurl curl_easy_setopt(curlhandle, CURLOPT_RESUME_FROM_LARGE, use_resume?local_file_len:0); curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, f); curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, wirtefunc); //curl_easy_setopt(curlhandle, CURLOPT_READFUNCTION, readfunc); //curl_easy_setopt(curlhandle, CURLOPT_READDATA, f); curl_easy_setopt(curlhandle, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L); r = curl_easy_perform(curlhandle); fclose(f); if (r == CURLE_OK) return 1; else { fprintf(stderr, "%s\n", curl_easy_strerror(r)); return 0; } } int main(int c, char **argv) { CURL *curlhandle = NULL; curl_global_init(CURL_GLOBAL_ALL); curlhandle = curl_easy_init(); //download(curlhandle, "ftp://user:pass@host/path/file", "C:\\file", 0, 3); download(curlhandle , "http://software.sky-union.cn/index.asp","/work/index.asp",1,3); curl_easy_cleanup(curlhandle); curl_global_cleanup(); return 0; }
// 采用CURLOPT_NOPROGRESS, CURLOPT_PROGRESSFUNCTION CURLOPT_PROGRESSDATA 实现文件传输进度提示功能 //函数采用了gtk库,故编译时需指定gtk库 //函数启动专门的线程用于显示gtk 进度条bar #include <stdio.h> #include <gtk/gtk.h> #include <curl/curl.h> #include <curl/types.h> /* new for v7 */ #include <curl/easy.h> /* new for v7 */ GtkWidget *Bar; ////这个函数是为了符合CURLOPT_WRITEFUNCTION而构造的 //完成数据保存功能 size_t my_write_func(void *ptr, size_t size, size_t nmemb, FILE *stream) { return fwrite(ptr, size, nmemb, stream); } //这个函数是为了符合CURLOPT_READFUNCTION而构造的 //数据上传时使用 size_t my_read_func(void *ptr, size_t size, size_t nmemb, FILE *stream) { return fread(ptr, size, nmemb, stream); } //这个函数是为了符合CURLOPT_PROGRESSFUNCTION而构造的 //显示文件传输进度,t代表文件大小,d代表传 输已经完成部分 int my_progress_func(GtkWidget *bar, double t, /* dltotal */ double d, /* dlnow */ double ultotal, double ulnow) { /* printf("%d / %d (%g %%)\n", d, t, d*100.0/t);*/ gdk_threads_enter(); gtk_progress_set_value(GTK_PROGRESS(bar), d*100.0/t); gdk_threads_leave(); return 0; } void *my_thread(void *ptr) { CURL *curl; CURLcode res; FILE *outfile; gchar *url = ptr; curl = curl_easy_init(); if(curl) { outfile = fopen("test.curl", "w"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_func); curl_easy_setopt(curl, CURLOPT_READFUNCTION, my_read_func); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress_func); curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, Bar); res = curl_easy_perform(curl); fclose(outfile); /* always cleanup */ curl_easy_cleanup(curl); } return NULL; } int main(int argc, char **argv) { GtkWidget *Window, *Frame, *Frame2; GtkAdjustment *adj; /* Must initialize libcurl before any threads are started */ curl_global_init(CURL_GLOBAL_ALL); /* Init thread */ g_thread_init(NULL); gtk_init(&argc, &argv); Window = gtk_window_new(GTK_WINDOW_TOPLEVEL); Frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(Frame), GTK_SHADOW_OUT); gtk_container_add(GTK_CONTAINER(Window), Frame); Frame2 = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(Frame2), GTK_SHADOW_IN); gtk_container_add(GTK_CONTAINER(Frame), Frame2); gtk_container_set_border_width(GTK_CONTAINER(Frame2), 5); adj = (GtkAdjustment*)gtk_adjustment_new(0, 0, 100, 0, 0, 0); Bar = gtk_progress_bar_new_with_adjustment(adj); gtk_container_add(GTK_CONTAINER(Frame2), Bar); gtk_widget_show_all(Window); if (!g_thread_create(&my_thread, argv[1], FALSE, NULL) != 0) g_warning("can't create the thread"); gdk_threads_enter(); gtk_main(); gdk_threads_leave(); return 0; }
FTP DOWNLOAD AND UPLOAD USE LIBCURL
#include <stdlib.h> #include <stdio.h> #include <curl/curl.h> #include <sys/stat.h> /* parse headers for Content-Length */ size_t getcontentlengthfunc(void *ptr, size_t size, size_t nmemb, void *stream) { int r; long len = 0; /* _snscanf() is Win32 specific */ //r = _snscanf(ptr, size * nmemb, "Content-Length: %ld\n", &len); r = sscanf((const char*)ptr, "Content-Length: %ld\n", &len); if (r) /* Microsoft: we don't read the specs */ *((long *) stream) = len; return size * nmemb; } /* discard downloaded data */ size_t discardfunc(void *ptr, size_t size, size_t nmemb, void *stream) { return size * nmemb; } //write data to upload size_t writefunc(void *ptr, size_t size, size_t nmemb, void *stream) { return fwrite(ptr, size, nmemb, (FILE*)stream); } /* read data to upload */ size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream) { FILE *f = (FILE*)stream; size_t n; if (ferror(f)) return CURL_READFUNC_ABORT; n = fread(ptr, size, nmemb, f) * size; return n; } int upload(CURL *curlhandle, const char * remotepath, const char * localpath, long timeout, long tries) { FILE *f; long uploaded_len = 0; CURLcode r = CURLE_GOT_NOTHING; int c; f = fopen(localpath, "rb"); if (f == NULL) { perror(NULL); return 0; } curl_easy_setopt(curlhandle, CURLOPT_UPLOAD, 1L); curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath); curl_easy_setopt(curlhandle, CURLOPT_USERPWD, "spider:spider"); if (timeout) curl_easy_setopt(curlhandle, CURLOPT_FTP_RESPONSE_TIMEOUT, timeout); curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, getcontentlengthfunc); curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &uploaded_len); curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, discardfunc); curl_easy_setopt(curlhandle, CURLOPT_READFUNCTION, readfunc); curl_easy_setopt(curlhandle, CURLOPT_READDATA, f); curl_easy_setopt(curlhandle, CURLOPT_FTPPORT, "-"); /* disable passive mode */ curl_easy_setopt(curlhandle, CURLOPT_FTP_CREATE_MISSING_DIRS, 1L); curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L); for (c = 0; (r != CURLE_OK) && (c < tries); c++) { /* are we resuming? */ if (c) { /* yes */ /* determine the length of the file already written */ /* * With NOBODY and NOHEADER, libcurl will issue a SIZE * command, but the only way to retrieve the result is * to parse the returned Content-Length header. Thus, * getcontentlengthfunc(). We need discardfunc() above * because HEADER will dump the headers to stdout * without it. */ curl_easy_setopt(curlhandle, CURLOPT_NOBODY, 1L); curl_easy_setopt(curlhandle, CURLOPT_HEADER, 1L); r = curl_easy_perform(curlhandle); if (r != CURLE_OK) continue; curl_easy_setopt(curlhandle, CURLOPT_NOBODY, 0L); curl_easy_setopt(curlhandle, CURLOPT_HEADER, 0L); fseek(f, uploaded_len, SEEK_SET); curl_easy_setopt(curlhandle, CURLOPT_APPEND, 1L); } else { /* no */ curl_easy_setopt(curlhandle, CURLOPT_APPEND, 0L); } r = curl_easy_perform(curlhandle); } fclose(f); if (r == CURLE_OK) return 1; else { fprintf(stderr, "%s\n", curl_easy_strerror(r)); return 0; } } // 下载 int download(CURL *curlhandle, const char * remotepath, const char * localpath, long timeout, long tries) { FILE *f; curl_off_t local_file_len = -1 ; long filesize =0 ; CURLcode r = CURLE_GOT_NOTHING; struct stat file_info; int use_resume = 0; //获取本地文件大小信息 if(stat(localpath, &file_info) == 0) { local_file_len = file_info.st_size; use_resume = 1; } //追加方式打开文件,实现断点续传 f = fopen(localpath, "ab+"); if (f == NULL) { perror(NULL); return 0; } curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath); curl_easy_setopt(curlhandle, CURLOPT_USERPWD, "spider:spider"); //连接超时设置 curl_easy_setopt(curlhandle, CURLOPT_CONNECTTIMEOUT, timeout); //设置头处理函数 curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, getcontentlengthfunc); curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &filesize); // 设置断点续传 curl_easy_setopt(curlhandle, CURLOPT_RESUME_FROM_LARGE, use_resume?local_file_len:0); curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, writefunc); curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, f); curl_easy_setopt(curlhandle, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L); r = curl_easy_perform(curlhandle); fclose(f); if (r == CURLE_OK) return 1; else { fprintf(stderr, "%s\n", curl_easy_strerror(r)); return 0; } } int main(int c, char **argv) { CURL *curlhandle = NULL; CURL *curldwn = NULL; curl_global_init(CURL_GLOBAL_ALL); curlhandle = curl_easy_init(); curldwn = curl_easy_init(); upload(curlhandle, "ftp://192.168.0.185/a/success", "D:/abc.jpg", 1, 3); download(curldwn, "ftp://192.168.0.185/a/success", "D:/abc1.jpg", 1, 3); curl_easy_cleanup(curlhandle); curl_easy_cleanup(curldwn); curl_global_cleanup(); return 0; }