1. 提供代码 重点关注curl_escape API #include <stdlib.h> #include <stdio.h> #include <sys/stat.h> #include <curl/curl.h> 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); printf("len: %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(stat(localpath, &file_info) == 0) { local_file_len = file_info.st_size; use_resume = 1; } f = fopen(localpath, "wb+"); 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; 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(); char *name = "我和我"; char *encode = curl_escape(name, strlen(name)); char str[1024] = {0}; snprintf(str, sizeof(str), "http://129.24.20.99:42/file/download?fileName=voiceLibrary/%s.mp3", encode); printf("str: %s\n", str); download(curlhandle, str,"./我和我.mp3",1,3); curl_easy_cleanup(curlhandle); curl_global_cleanup(); return 0; }
原本经过一些列的curl的API,并且通过抓包发现
mp3的名字是没通过编码处理的,此时服务器返回FIN借以终结tcp连接,开始怀疑是tcp连接的问题,对比wget是一样的tcp链路。
2. 下文可以继续深入研究curl_escape 的具体实现。
Life is mess, don't let mess mess us.