wget.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /*
  2. * @build: make examples
  3. * @server bin/httpd -s restart -d
  4. * @client bin/wget 127.0.0.1:8080/
  5. */
  6. #include "requests.h"
  7. static int wget(const char* url, const char* filepath) {
  8. HFile file;
  9. if (file.open(filepath, "wb") != 0) {
  10. fprintf(stderr, "Failed to open file %s\n", filepath);
  11. return -20;
  12. }
  13. printf("Save file to %s ...\n", filepath);
  14. // HEAD
  15. auto resp = requests::head(url);
  16. if (resp == NULL) {
  17. fprintf(stderr, "request failed!\n");
  18. return -1;
  19. }
  20. printd("%s", resp->Dump(true, false).c_str());
  21. if (resp->status_code == HTTP_STATUS_NOT_FOUND) {
  22. fprintf(stderr, "404 Not Found\n");
  23. return -1;
  24. }
  25. bool use_range = false;
  26. int range_bytes = 1 << 20; // 1M
  27. std::string accept_ranges = resp->GetHeader("Accept-Ranges");
  28. size_t content_length = hv::from_string<size_t>(resp->GetHeader("Content-Length"));
  29. // use Range if server accept_ranges and content_length > 1M
  30. if (resp->status_code == 200 &&
  31. accept_ranges == "bytes" &&
  32. content_length > range_bytes) {
  33. use_range = true;
  34. }
  35. // GET
  36. if (!use_range) {
  37. resp = requests::get(url);
  38. if (resp == NULL) {
  39. fprintf(stderr, "request failed!\n");
  40. return -1;
  41. }
  42. printd("%s", resp->Dump(true, false).c_str());
  43. file.write(resp->body.data(), resp->body.size());
  44. printf("progress: %ld/%ld = 100%%\n", (long)resp->body.size(), (long)resp->body.size());
  45. return 0;
  46. }
  47. // Range: bytes=from-to
  48. long from = 0, to = 0;
  49. int last_progress = 0;
  50. http_client_t* cli = http_client_new();
  51. HttpRequestPtr req(new HttpRequest);
  52. req->method = HTTP_GET;
  53. req->url = url;
  54. while (from < content_length) {
  55. to = from + range_bytes - 1;
  56. if (to >= content_length) to = content_length - 1;
  57. req->SetRange(from, to);
  58. printd("%s", req->Dump(true, false).c_str());
  59. int ret = http_client_send(cli, req.get(), resp.get());
  60. if (ret != 0) {
  61. fprintf(stderr, "request failed!\n");
  62. return -1;
  63. }
  64. printd("%s", resp->Dump(true, false).c_str());
  65. file.write(resp->body.data(), resp->body.size());
  66. from = to + 1;
  67. // print progress
  68. int cur_progress = from * 100 / content_length;
  69. if (cur_progress > last_progress) {
  70. printf("\rprogress: %ld/%ld = %d%%", (long)from, (long)content_length, (int)cur_progress);
  71. fflush(stdout);
  72. last_progress = cur_progress;
  73. }
  74. }
  75. printf("\n");
  76. http_client_del(cli);
  77. return 0;
  78. }
  79. int main(int argc, char** argv) {
  80. if (argc < 2) {
  81. printf("Usage: %s url [filepath]\n", argv[0]);
  82. return -10;
  83. }
  84. const char* url = argv[1];
  85. const char* filepath = "index.html";
  86. if (argc > 2) {
  87. filepath = argv[2];
  88. } else {
  89. const char* path = strrchr(url, '/');
  90. if (path && path[1]) {
  91. filepath = path + 1;
  92. }
  93. }
  94. wget(url, filepath);
  95. return 0;
  96. }