程序不显示下载速度和文件大小 (curl)
Program does not display download speed and size of file (curl)
我在 Ubuntu 上遇到卷曲问题。我希望它显示下载文件的下载速度和大小。我已经声明了 double* sized 和 double* speedd 以及 CURL *curl。我不断收到分段错误。程序编译到 "File downloaded" 的时刻。它还应该告诉我来自 CURLINFO_SIZE_DOWNLOAD 和 CURLINFO_SPEED_DOWNLOAD 的信息。请帮忙。
#define CURL_STATICLIB
#include <stdio.h>
#include <curl/curl.h>
#include <string.h>
#include <stdlib.h>
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
size_t written;
written = fwrite(ptr, size, nmemb, stream);
return written;
}
int main(void)
{
CURL *curl;
FILE *fp;
CURLcode res;
FILE *stream = stdout;
int x;
char y[1024];
double* sized;
double* speedd;
char* name = calloc(1, 1024);
char* outfilename;
char* path_pdf = "/home/user/Desktop/%s.pdf";
char* path_jpg = "/home/user/Desktop/%s.jpg";
char* path_txt = "/home/user/Desktop/%s.txt";
char* path_mp3 = "/home/user/Desktop/%s.mp3";
char* path_avi = "/home/user/Desktop/%s.avi";
printf("Enter file url: \n"); // for example http://oi58.tinypic.com/15nk3de.jpg
scanf ("%s",y);
char *url = y;
printf("Type name of file \n");
scanf("%s",name);
char *result_pdf = malloc(strlen(path_pdf) - 2 + strlen(name) + 1);
sprintf(result_pdf, path_pdf, name);
char *result_jpg = malloc(strlen(path_jpg) - 2 + strlen(name) + 1);
sprintf(result_jpg, path_jpg, name);
char *result_txt = malloc(strlen(path_txt) - 2 + strlen(name) + 1);
sprintf(result_txt, path_txt, name);
char *result_mp3 = malloc(strlen(path_mp3) - 2 + strlen(name) + 1);
sprintf(result_mp3, path_mp3, name);
char *result_avi = malloc(strlen(path_avi) - 2 + strlen(name) + 1);
sprintf(result_avi, path_avi, name);
printf("Choose type of file:\n [0] - pdf\n [1] - jpg\n [2] - txt\n [3] - mp3\n [4] - avi\n "); //choose 1
scanf("%d",&x);
switch(x){
case 0:
outfilename = result_pdf;
break;
case 1:
outfilename = result_jpg;
break;
case 2:
outfilename = result_txt;
break;
case 3:
outfilename = result_mp3;
break;
case 4:
outfilename = result_avi;
break;
}
curl = curl_easy_init();
if (curl)
{
fp = fopen(outfilename,"wb");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
printf("Download started!\n\n");
curl_easy_setopt (curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
if(res == CURLE_OK) {
printf("File downloaded!\n\n");}
else {
printf("Transfer failed!");}
curl_easy_getinfo(curl,CURLINFO_SIZE_DOWNLOAD,&sized);
fprintf(stream,"%.3f \n", sized);
curl_easy_getinfo(curl,CURLINFO_SPEED_DOWNLOAD,&speedd);
fprintf(stream, "%.3f \n", speedd);
curl_easy_cleanup(curl);
fclose(fp);
}
return 0;
}
您在问题中提供的代码存在一些问题:
你没有包括 stdlib.h
。
name
未分配
您还没有分配 space 来存储 uri 路径部分的输入。当您调用 scanf(3)
读取路径名时,它会尝试将其存储到 name
引用的内存位置。由于 name
未初始化,因此指针的值未定义。这会导致分段错误。
为 name
分配内存或将类型从指针更改为数组,大小适当。
char *name = calloc(1, 1024);
printf("Type name of file \n");
scanf("%s",name);
或
char name[1024];
printf("Type name of file \n");
scanf("%s",name);
两者都可能会很好地满足您的需求。但是,请注意这些方法会引入堆或堆栈溢出错误,因为 scanf(3)
不执行边界检查。这种事情的通常模式是使用 fgets(3)
读取一行输入并使用 sscanf(3)
对其进行标记。在这种情况下,你真的只需要 fgets(3)
.
不使用gets(3)
。
- 您没有在打印成功时打印下载信息。
在您的代码中,您仅在失败时从 cURL 打印出状态信息:
if (res == CURLE_OK) {
printf("File downloaded!\n\n");
} else {
printf("Transfer failed!");}
curl_easy_getinfo(curl,CURLINFO_SIZE_DOWNLOAD,sized);
curl_easy_getinfo(curl,CURLINFO_SPEED_DOWNLOAD,speedd);
curl_easy_cleanup(curl);
fclose(fp);
}
相反,我认为你的意思是:
if (res == CURLE_OK) {
printf("File downloaded!\n\n");
} else {
printf("Transfer failed!");}
}
curl_easy_getinfo(curl,CURLINFO_SIZE_DOWNLOAD,sized);
curl_easy_getinfo(curl,CURLINFO_SPEED_DOWNLOAD,speedd);
curl_easy_cleanup(curl);
fclose(fp);
我猜这个问题的原因是因为你的代码风格。看起来你至少是 C 的半新手。以一致的风格编写将提高你的代码可读性并帮助你避免这样的错误。只要你坚持,你使用什么样的风格并不重要。
- 您的程序的行为超出预期,增加了代码大小
您的程序架构有点迟钝。更常见的是允许用户在命令行上指定参数。在这种情况下,您可以选择命名输出文件和命名源 URI。
即使您这样做是为了学习标准库,也最好继续您的实现以更符合预期的方式运行。另请参阅 getopt(3)
联机帮助页。您可能会发现,一旦执行此操作,您的程序的大小就会缩小大约一半。
程序越小越好。
- 您将未定义的指针值传递给
curl_easy_getinfo
。
您已声明
double* sized;
double* speedd;
但没有为这些提供存储空间。当您调用 curl_easy_getinfo
时,它会崩溃。您在评论中提到您通过将地址传递给 curl_easy_getinfo
来解决此问题。这会停止崩溃,因为您已经提供了地址的存储空间。但是,如果您尝试打印该信息,您要么一无所获,要么再次崩溃。
相反,您想要的是:
double sized;
double speedd;
...
curl_easy_getinfo(curl,CURLINFO_SIZE_DOWNLOAD,&sized);
curl_easy_getinfo(curl,CURLINFO_SPEED_DOWNLOAD,&speedd);
- 您没有在任何地方打印出尺寸或速度。
获得它们后,您不会在 main
函数结束时打印尺寸或速度。您需要将它们打印出来:
printf("Size: %g KB\nSpeed: %g KB/s\n", sized / 1024., speedd / 1024.);
经过这些更改,这是完整 运行:
的输出
Enter file url:
http://oi58.tinypic.com/15nk3de.jpg
Type name of file
foo.jpg
Choose type of file:
[0] - pdf
[1] - jpg
[2] - txt
[3] - mp3
[4] - avi
1
Download started!
* Hostname was NOT found in DNS cache
* Trying 209.17.68.209...
* Connected to oi58.tinypic.com (209.17.68.209) port 80 (#0)
> GET /15nk3de.jpg HTTP/1.1
Host: oi58.tinypic.com
Accept: */*
< HTTP/1.1 200 OK
* Server Apache is not blacklisted
< Server: Apache
< Last-Modified: Thu, 13 Feb 2014 19:51:01 GMT
< ETag: "1d7a5-4f24f024dc8be"
< Cache-Control: max-age=21600
< Expires: Sun, 04 Jan 2015 00:02:56 GMT
< Content-Type: image/jpeg
< Content-Length: 120741
< Accept-Ranges: bytes
< Date: Sat, 03 Jan 2015 19:24:19 GMT
< X-Varnish: 1269536769 1268437896
< Age: 4883
< Via: 1.1 varnish
< Connection: keep-alive
< X-Varnish-Server: den2tpv65
< X-Cache: HIT
<
* Connection #0 to host oi58.tinypic.com left intact
File downloaded!
Size: 117.911 KB
Speed: 169.138 KB/s
我在 Ubuntu 上遇到卷曲问题。我希望它显示下载文件的下载速度和大小。我已经声明了 double* sized 和 double* speedd 以及 CURL *curl。我不断收到分段错误。程序编译到 "File downloaded" 的时刻。它还应该告诉我来自 CURLINFO_SIZE_DOWNLOAD 和 CURLINFO_SPEED_DOWNLOAD 的信息。请帮忙。
#define CURL_STATICLIB
#include <stdio.h>
#include <curl/curl.h>
#include <string.h>
#include <stdlib.h>
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
size_t written;
written = fwrite(ptr, size, nmemb, stream);
return written;
}
int main(void)
{
CURL *curl;
FILE *fp;
CURLcode res;
FILE *stream = stdout;
int x;
char y[1024];
double* sized;
double* speedd;
char* name = calloc(1, 1024);
char* outfilename;
char* path_pdf = "/home/user/Desktop/%s.pdf";
char* path_jpg = "/home/user/Desktop/%s.jpg";
char* path_txt = "/home/user/Desktop/%s.txt";
char* path_mp3 = "/home/user/Desktop/%s.mp3";
char* path_avi = "/home/user/Desktop/%s.avi";
printf("Enter file url: \n"); // for example http://oi58.tinypic.com/15nk3de.jpg
scanf ("%s",y);
char *url = y;
printf("Type name of file \n");
scanf("%s",name);
char *result_pdf = malloc(strlen(path_pdf) - 2 + strlen(name) + 1);
sprintf(result_pdf, path_pdf, name);
char *result_jpg = malloc(strlen(path_jpg) - 2 + strlen(name) + 1);
sprintf(result_jpg, path_jpg, name);
char *result_txt = malloc(strlen(path_txt) - 2 + strlen(name) + 1);
sprintf(result_txt, path_txt, name);
char *result_mp3 = malloc(strlen(path_mp3) - 2 + strlen(name) + 1);
sprintf(result_mp3, path_mp3, name);
char *result_avi = malloc(strlen(path_avi) - 2 + strlen(name) + 1);
sprintf(result_avi, path_avi, name);
printf("Choose type of file:\n [0] - pdf\n [1] - jpg\n [2] - txt\n [3] - mp3\n [4] - avi\n "); //choose 1
scanf("%d",&x);
switch(x){
case 0:
outfilename = result_pdf;
break;
case 1:
outfilename = result_jpg;
break;
case 2:
outfilename = result_txt;
break;
case 3:
outfilename = result_mp3;
break;
case 4:
outfilename = result_avi;
break;
}
curl = curl_easy_init();
if (curl)
{
fp = fopen(outfilename,"wb");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
printf("Download started!\n\n");
curl_easy_setopt (curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
if(res == CURLE_OK) {
printf("File downloaded!\n\n");}
else {
printf("Transfer failed!");}
curl_easy_getinfo(curl,CURLINFO_SIZE_DOWNLOAD,&sized);
fprintf(stream,"%.3f \n", sized);
curl_easy_getinfo(curl,CURLINFO_SPEED_DOWNLOAD,&speedd);
fprintf(stream, "%.3f \n", speedd);
curl_easy_cleanup(curl);
fclose(fp);
}
return 0;
}
您在问题中提供的代码存在一些问题:
你没有包括
stdlib.h
。name
未分配
您还没有分配 space 来存储 uri 路径部分的输入。当您调用 scanf(3)
读取路径名时,它会尝试将其存储到 name
引用的内存位置。由于 name
未初始化,因此指针的值未定义。这会导致分段错误。
为 name
分配内存或将类型从指针更改为数组,大小适当。
char *name = calloc(1, 1024);
printf("Type name of file \n");
scanf("%s",name);
或
char name[1024];
printf("Type name of file \n");
scanf("%s",name);
两者都可能会很好地满足您的需求。但是,请注意这些方法会引入堆或堆栈溢出错误,因为 scanf(3)
不执行边界检查。这种事情的通常模式是使用 fgets(3)
读取一行输入并使用 sscanf(3)
对其进行标记。在这种情况下,你真的只需要 fgets(3)
.
不使用gets(3)
。
- 您没有在打印成功时打印下载信息。
在您的代码中,您仅在失败时从 cURL 打印出状态信息:
if (res == CURLE_OK) {
printf("File downloaded!\n\n");
} else {
printf("Transfer failed!");}
curl_easy_getinfo(curl,CURLINFO_SIZE_DOWNLOAD,sized);
curl_easy_getinfo(curl,CURLINFO_SPEED_DOWNLOAD,speedd);
curl_easy_cleanup(curl);
fclose(fp);
}
相反,我认为你的意思是:
if (res == CURLE_OK) {
printf("File downloaded!\n\n");
} else {
printf("Transfer failed!");}
}
curl_easy_getinfo(curl,CURLINFO_SIZE_DOWNLOAD,sized);
curl_easy_getinfo(curl,CURLINFO_SPEED_DOWNLOAD,speedd);
curl_easy_cleanup(curl);
fclose(fp);
我猜这个问题的原因是因为你的代码风格。看起来你至少是 C 的半新手。以一致的风格编写将提高你的代码可读性并帮助你避免这样的错误。只要你坚持,你使用什么样的风格并不重要。
- 您的程序的行为超出预期,增加了代码大小
您的程序架构有点迟钝。更常见的是允许用户在命令行上指定参数。在这种情况下,您可以选择命名输出文件和命名源 URI。
即使您这样做是为了学习标准库,也最好继续您的实现以更符合预期的方式运行。另请参阅 getopt(3)
联机帮助页。您可能会发现,一旦执行此操作,您的程序的大小就会缩小大约一半。
程序越小越好。
- 您将未定义的指针值传递给
curl_easy_getinfo
。
您已声明
double* sized;
double* speedd;
但没有为这些提供存储空间。当您调用 curl_easy_getinfo
时,它会崩溃。您在评论中提到您通过将地址传递给 curl_easy_getinfo
来解决此问题。这会停止崩溃,因为您已经提供了地址的存储空间。但是,如果您尝试打印该信息,您要么一无所获,要么再次崩溃。
相反,您想要的是:
double sized;
double speedd;
...
curl_easy_getinfo(curl,CURLINFO_SIZE_DOWNLOAD,&sized);
curl_easy_getinfo(curl,CURLINFO_SPEED_DOWNLOAD,&speedd);
- 您没有在任何地方打印出尺寸或速度。
获得它们后,您不会在 main
函数结束时打印尺寸或速度。您需要将它们打印出来:
printf("Size: %g KB\nSpeed: %g KB/s\n", sized / 1024., speedd / 1024.);
经过这些更改,这是完整 运行:
的输出Enter file url:
http://oi58.tinypic.com/15nk3de.jpg
Type name of file
foo.jpg
Choose type of file:
[0] - pdf
[1] - jpg
[2] - txt
[3] - mp3
[4] - avi
1
Download started!
* Hostname was NOT found in DNS cache
* Trying 209.17.68.209...
* Connected to oi58.tinypic.com (209.17.68.209) port 80 (#0)
> GET /15nk3de.jpg HTTP/1.1
Host: oi58.tinypic.com
Accept: */*
< HTTP/1.1 200 OK
* Server Apache is not blacklisted
< Server: Apache
< Last-Modified: Thu, 13 Feb 2014 19:51:01 GMT
< ETag: "1d7a5-4f24f024dc8be"
< Cache-Control: max-age=21600
< Expires: Sun, 04 Jan 2015 00:02:56 GMT
< Content-Type: image/jpeg
< Content-Length: 120741
< Accept-Ranges: bytes
< Date: Sat, 03 Jan 2015 19:24:19 GMT
< X-Varnish: 1269536769 1268437896
< Age: 4883
< Via: 1.1 varnish
< Connection: keep-alive
< X-Varnish-Server: den2tpv65
< X-Cache: HIT
<
* Connection #0 to host oi58.tinypic.com left intact
File downloaded!
Size: 117.911 KB
Speed: 169.138 KB/s