C语言CURL网络连接 为了下载做准备
2022/3/2 23:15:49
本文主要是介绍C语言CURL网络连接 为了下载做准备,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
难点补充
1
oid SendRequest(RequestContext *request_context) { if (request_context->is_running) { PRINTLNF("request already running ...."); return; } CURL *curl = curl_easy_init(); if (!curl) { request_context->curl_code = -1; return; } //参数配置 curl_easy_setopt(curl, CURLOPT_URL, request_context->url); //对于http 返回请求302 重定向做一处理 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); //这里解析文件名称 文件大小 文件!是什么 curl_easy_setopt(curl, CURLOPT_NOBODY, request_context->header_only); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, CurlHeaderFunction); curl_easy_setopt(curl, CURLOPT_HEADERDATA, request_context); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlBodyFunction); curl_easy_setopt(curl, CURLOPT_WRITEDATA, request_context); //进度回调 if (request_context->request->progress_callback) { curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, CurlProgressFunction); curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, request_context); } //断点续传 char content_range[40]; if (request_context->range_start >= 0 && request_context->range_end >= 0) { //先下载一部分 //9223372036854775808-9223372036854775808 | 838TB snprintf(content_range, 40, "%llu-%llu", request_context->range_start, request_context->range_end); } else if (request_context->range_start >= 0) { //暂停后开始 //9223372036854775808- | 838TB snprintf(content_range, 40, "%llu-", request_context->range_start); } else if (request_context->range_end >= 0) { //-9223372036854775808 | 838TB snprintf(content_range, 40, "-%llu", request_context->range_end); } else { // no range request. content_range[0] = 0; } if (content_range[0] > 0) { PRINTLNF("content-range: %s", content_range); CURLcode code = curl_easy_setopt(curl, CURLOPT_RANGE, content_range); } curl_easy_setopt(curl, CURLOPT_CAINFO, "cacert.pem"); curl_easy_setopt(curl, CURLOPT_CAPATH, "cacert.pem"); request_context->curl = curl; request_context->is_running = 1; //请求得到返回值 调用这句话的时候 请求 request_context->curl_code = curl_easy_perform(curl); request_context->curl = NULL; request_context->is_running = 0; curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &request_context->file_size); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &request_context->response_code); // 找不到文件名 header里面没有对应的字段 解析不出来字段 就根据URL 解析 if (request_context->header_only && !request_context->output_filename) { RetrieveOutputNameFromUrl(request_context); } if (request_context->output_stream) { fclose(request_context->output_stream); request_context->output_stream = NULL; } curl_easy_cleanup(curl); }
对于断点设定就是结构体里面初始化两个变量 然后根据里面的值进行判断下载 一般就是暂停保存一下 然后开始的时候读取那个点
typedef struct RequestContext { Request *request; char *url; char *download_directory; int header_only; int64_t range_start; int64_t range_end;
还有就是多线程下载要注意的问题
RequestContext *CreateRequestContext(Request *request, const char *url, const char *directory) { CREATE_OBJECT_CLEANED(RequestContext, context); context->request = request; //复制一下为多线程做准备 url 是复制一份 以防止多线程私有栈被释放 context->url = strdup(url); context->download_directory = strdup(directory); context->file_size = 0; context->range_start = -1; context->range_end = -1; context->is_running = 0; return context; }
header中找不到字段的话去url 里面找
// 找不到文件名 header里面没有对应的字段 解析不出来字段 就根据URL 解析 if (request_context->header_only && !request_context->output_filename) { RetrieveOutputNameFromUrl(request_context); } // header 里面没有字段 就根据 url 解析 就是解析 task 里面的最后一个文件名 static int RetrieveOutputNameFromUrl(RequestContext *context) { int result = RESULT_OK; char output_filename[1024]; char const *url = context->url; // http://www.bennyhuo.com/testdata/三国演义.txt?param=1 // http://www.bennyhuo.com/testdata/三国演义.txt#chapter1 // http://www.bennyhuo.com/testdata/%E4%B8%89%E5%9B%BD%E6%BC%94%E4%B9%89.txt?param=1 url = strrchr(url, '/'); url++; int i = 0; while (*url != '\0' && *url != '?' && *url != '#') { output_filename[i++] = *url++; } output_filename[i] = '\0'; char *url_decoded_filename = curl_easy_unescape(context->curl, output_filename, 0, NULL); context->output_filename = strdup(url_decoded_filename); curl_free(url_decoded_filename); return result; }
printf("%.*s", (int) buffer_size, buffer); 传入点 * 自己设定字符串大小
在http 的url 协议中是不会自己传递 汉字的都是编码后的结果 所以拿到的都是编码后的内容 要进行解码
strdup()在内部调用了malloc()为变量分配内存,不需要使用返回的字符串时,需要用free()释放相应的内存空间,否则会造成内存泄漏。
static int RetrieveOutputNameFromUrl(RequestContext *context) { int result = RESULT_OK; char output_filename[1024]; char const *url = context->url; // http://www.bennyhuo.com/testdata/三国演义.txt?param=1 // http://www.bennyhuo.com/testdata/三国演义.txt#chapter1 // http://www.bennyhuo.com/testdata/%E4%B8%89%E5%9B%BD%E6%BC%94%E4%B9%89.txt?param=1 url = strrchr(url, '/'); url++; int i = 0; while (*url != '\0' && *url != '?' && *url != '#') { output_filename[i++] = *url++; } output_filename[i] = '\0'; char *url_decoded_filename = curl_easy_unescape(context->curl, output_filename, 0, NULL); context->output_filename = strdup(url_decoded_filename); curl_free(url_decoded_filename); return result;
如果Http 返回值是206 是支持断点续传
这篇关于C语言CURL网络连接 为了下载做准备的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-09-28pyqt 怎么打包整个项目-icode9专业技术文章分享
- 2024-09-28laravel Commands 创建带有参数的 Artisan 命令的步骤和示例-icode9专业技术文章分享
- 2024-09-28antd怎么实现渲染tiff图片-icode9专业技术文章分享
- 2024-09-28英文半角中划线和中文全角的中划线有什么区别-icode9专业技术文章分享
- 2024-09-28nvm npm 和node 他们之间有什么关系-icode9专业技术文章分享
- 2024-09-28Node Version Manager (nvm)使用教程-icode9专业技术文章分享
- 2024-09-28nvm命令太慢,是什么原因-icode9专业技术文章分享
- 2024-09-28Kotlin 如何增加、删除和修改 MutableStateFlow 中的值。-icode9专业技术文章分享
- 2024-09-28Kotlin的stateFlow.update 写法介绍-icode9专业技术文章分享
- 2024-09-28kotlin 怎么获取当前时间格式-icode9专业技术文章分享