In fact, this HTTP downloader function has been quite perfect, support: speed limit, post delivery and upload, custom HTTP header, set user agent, set range and timeout
And it is not only download HTTP, because the use of the stream, so also support other protocols, you can also use it to copy between files, pure TCP download and so on.
* *//////////////////////////////////////////////////////////////////////////////////////* includes/#include ".
/demo.h "* *//////////////////////////////////////////////////////////////////////////////////////* Types * *
typedef struct __TB_DEMO_CONTEXT_T {//verbose tb_bool_t verbose;
}tb_demo_context_t; * *//////////////////////////////////////////////////////////////////////////////////////* func/#ifdef TB_CONFIG _module_have_object static tb_bool_t Tb_demo_http_post_func (tb_size_t State, tb_hize_t offset, tb_hong_t size, tb_hize_
T save, tb_size_t rate, tb_cpointer_t priv) {//percent tb_size_t-percent = 0;
if (Size > 0) percent = (tb_size_t) (offset */size);
else if (state = = tb_state_closed) percent = 100; Trace Tb_trace_i (post:%llu, Rate:%lu bytes/s, Percent:%lu%%, State:%s), save, rate, percent, TB_STATE_CSTR (state
));
OK return tb_true; Static tb_bool_t Tb_demo_stream_head_func (tb_char_t const* line, tb_cpointer_t priv) {tb_printf ("Response:%s\n", line);
return tb_true; Static tb_bool_t Tb_demo_stream_save_func (tb_size_t State, tb_hize_t offset, tb_hong_t size, tb_hize_t save, tb_size_t R
Ate, tb_cpointer_t priv) {//Check tb_demo_context_t* context = (tb_demo_context_t*) priv;
Tb_assert_and_check_return_val (context, tb_false);
Print verbose info if (context->verbose) {//percent tb_size_t percent = 0;
if (Size > 0) percent = (tb_size_t) (offset */size);
else if (state = = tb_state_closed) percent = 100; Trace tb_printf (Save:%llu bytes, rate:%lu bytes/s, Percent:%lu%%, State:%s\n), save, rate, percent, tb_state_c
STR (state));
}//OK return tb_true; }/*//////////////////////////////////////////////////////////////////////////////////////* Globals/static TB_OP tion_item_t g_options[] = {'-', ' gzip ', Tb_option_mode_key, Tb_option_type_bool, ' Enable gzip '}, {'-', ' No-verbosE ", Tb_option_mode_key, Tb_option_type_bool," Disable verbose info "}, {' d '," Debug ", Tb_option_mode_key, Tb_option_type_bool, "Enable Debug Info"}, {' K ', ' keep-alive ', Tb_option_mode_key, Tb_option_type_bool , "Keep Alive"}, {' H ', ' header ', Tb_option_mode_key_val, Tb_option_type_cstr, "the Custem http Heade R "}, {'-'," Post-data ", Tb_option_mode_key_val, Tb_option_type_cstr," set the Post Data "}, {'-'," post- File ", Tb_option_mode_key_val, Tb_option_type_cstr," set the Post file "}, {'-', ' range ', Tb_option_mode_k Ey_val, Tb_option_type_cstr, "Set the Range"}, {'-', ' timeout ', Tb_option_mode_key_val, Tb_option_type_ INTEGER, "Set the Timeout"}, {'-', ' limitrate ', Tb_option_mode_key_val, Tb_option_type_integer, ' Set the L Imitrate "}, {' H '," Help ", Tb_option_mode_key, Tb_option_type_bool," Display this Help and exit "}, {'- ', ' url ', tb_option_mode_val, Tb_option_type_cstr, "The url"}, {'-', Tb_null, Tb_option_mode_more, Tb_option_type_n
One, Tb_null}}; /*//////////////////////////////////////////////////////////////////////////////////////* Main/tb_int_t Tb_demo
_stream_main (tb_int_t argc, tb_char_t** argv) {//done tb_option_ref_t option = tb_null;
tb_stream_ref_t istream = Tb_null;
tb_stream_ref_t ostream = tb_null;
tb_stream_ref_t pstream = tb_null;
do {//init option option = Tb_option_init ("Stream", "the Stream demo", g_options);
Tb_assert_and_check_break (option); Done option if (tb_option_done (option, argc-1, &argv[1)) {//debug & Verbose tb_bool_t
debug = tb_option_find (option, "Debug"); tb_bool_t verbose = tb_option_find (option, "No-verbose")?
Tb_false:tb_true; Done URL if (tb_option_find (option, "url")) {//init istream istream = Tb_stReam_init_from_url (option, "url") (TB_OPTION_ITEM_CSTR);
Tb_assert_and_check_break (IStream);
Ctrl HTTP if (Tb_stream_type (istream) = = tb_stream_type_http) {//enable gzip? if (tb_option_find (option, "gzip")) {//Auto unzip if (!tb_stream_ctrl (IStream, Tb_stre
Am_ctrl_http_set_auto_unzip, 1)) break; Need gzip if (!tb_stream_ctrl (IStream, Tb_stream_ctrl_http_set_head, "accept-encoding", "gzip,deflate") BR
Eak
}//Enable Debug?
if (!tb_stream_ctrl (IStream, Tb_stream_ctrl_http_set_head_func, Debug? tb_demo_stream_head_func:tb_null)) break;
Custem header?
if (tb_option_find (option, "header") {//init tb_string_t key;
Tb_string_t Val;
Tb_string_init (&key);
Tb_string_init (&val); Done tb_bool_t k = TB_true;
tb_char_t const* p = tb_option_item_cstr (option, "header");
while (*p) {//is key?
if (k) {if (*p!= ': ' &&!tb_isspace (*p)) Tb_string_chrcat (&key, *p++);
else if (*p = = ': ') {//Skip ': ' p++;
Skip space while (*p && tb_isspace (*p)) p++;
Is val now k = Tb_false;
else p++;
}/Is Val?
else {if (*p!= '; ') Tb_string_chrcat (&val, *p++);
else {//skip '; '
p++;
Skip space while (*p && tb_isspace (*p)) p++; Set Header if (Tb_string_size (&key) && Tb_string_size (&val)) {if (Debug) tb_printf ("header:%s:%s\n", Tb_string_cstr (
&key), Tb_string_cstr (&val)); if (!tb_stream_ctrl (IStream, Tb_stream_ctrl_http_set_head, Tb_string_cstr (&key), Tb_string_cstr (&val))
Break
}//is key now k = Tb_true;
Clear Key & Val Tb_string_clear (&key);
Tb_string_clear (&val); }}//Set header if (Tb_string_size (&key) && Tb_string_ Size (&val) {if (debug) tb_printf (header:%s:%s\n), Tb_string_cstr (&key), Tb_string_c
STR (&val)); if (!tb_stream_ctrl (IStream, Tb_stream_ctrl_http_set_head, Tb_string_cstr (&key), Tb_string_cstr (&val))
Break }//Exit Tb_string_exit (&key);
Tb_string_exit (&val);
}//Keep alive? if (tb_option_find (option, "keep-alive")) {if (!tb_stream_ctrl (IStream, Tb_stream_ctrl_http_set_hea
D, "Connection", "keep-alive") break;
}//Post-data? if (tb_option_find (option, "Post-data")) {tb_char_t const* post_data = tb_option_item_cstr (option,
"Post-data");
tb_hize_t post_size = Tb_strlen (Post_data);
if (!tb_stream_ctrl (IStream, Tb_stream_ctrl_http_set_method, tb_http_method_post)) break;
if (!tb_stream_ctrl (IStream, Tb_stream_ctrl_http_set_post_data, Post_data, post_size)) break;
if (!tb_stream_ctrl (IStream, Tb_stream_ctrl_http_set_post_func, Tb_demo_http_post_func)) break;
if (Debug) tb_printf ("Post:%llu\n", post_size);
}//Post-file? else if (tb_option_find (option, "Post-file")) {tb_char_tconst* url = tb_option_item_cstr (option, "Post-file");
if (!tb_stream_ctrl (IStream, Tb_stream_ctrl_http_set_method, tb_http_method_post)) break;
if (!tb_stream_ctrl (IStream, Tb_stream_ctrl_http_set_post_url, URL)) break;
if (!tb_stream_ctrl (IStream, Tb_stream_ctrl_http_set_post_func, Tb_demo_http_post_func)) break;
if (Debug) tb_printf ("Post:%s\n", url); }//Set range if (tb_option_find (option, "range") {tb_char_t const* p = t
B_OPTION_ITEM_CSTR (option, "range");
if (p) {//the BOF tb_hize_t EOF = 0;
tb_hize_t BOF = Tb_atoll (p);
while (*p && tb_isdigit (*p)) p++;
if (*p = = '-') {p++;
EOF = Tb_atoll (p);
} if (!tb_stream_ctrl (IStream, Tb_stream_ctrl_http_set_range, BOF, EOF)) break;
}//Set timeout if (tb_option_find (option, "timeout")) {tb_size_t timeout = tb_option_item_uint32 (option, "timeout
");
if (!tb_stream_ctrl (IStream, Tb_stream_ctrl_set_timeout, TIMEOUT)) break; }//Print verbose info if (verbose) tb_printf ("Open:%s:..
\ n ", tb_option_item_cstr (option," url ")); Open IStream if (!tb_stream_open (IStream)) {//Print verbose info if (verbose) TB
_printf ("Open:%s\n", Tb_state_cstr (Tb_stream_state (IStream));
Break
}//Print verbose info if (verbose) tb_printf ("open:ok\n"); Init ostream if (tb_option_find (option, "MORE0")) {//the path tb_char_t const* PA
th = tb_option_item_cstr (option, "more0"); init ostream = tb_stream_init_from_file (path, TB_FILE_MODE_RW | Tb_file_mode_creat | Tb_file_mode_binary |
TB_FILE_MODE_TRUNC); Print Verbose info
if (verbose) tb_printf ("Save:%s\n", path); else {//the name tb_char_t const* name = TB_STRRCHR tb_option_item_cstr (option, "U
RL "), '/');
if (!name) name = TB_STRRCHR (option, "url"), ' \ \ ' (TB_OPTION_ITEM_CSTR);
if (!name) name = "/stream.file";
The path tb_char_t PATH[TB_PATH_MAXN] = {0};
if (Tb_directory_curt (path, TB_PATH_MAXN)) Tb_strcat (path, name);
else break; init file Ostream = tb_stream_init_from_file (path, TB_FILE_MODE_RW | Tb_file_mode_creat | Tb_file_mode_binary |
TB_FILE_MODE_TRUNC);
Print verbose info if (verbose) tb_printf ("Save:%s\n", path);
} tb_assert_and_check_break (Ostream);
The limit rate tb_size_t limitrate = 0;
if (tb_option_find (option, "Limitrate")) Limitrate = tb_option_item_uint32 (option, "limitrate");
Save it tb_hong_t save = 0;
tb_demo_context_t context = {0};
Context.verbose = verbose;
if ((save = Tb_transfer_done (IStream, Ostream, Limitrate, Tb_demo_stream_save_func, &context)) < 0) break;
else tb_option_help (option);
else tb_option_help (option);
while (0);
Exit Pstream if (pstream) tb_stream_exit (pstream);
Pstream = Tb_null;
Exit IStream if (IStream) Tb_stream_exit (IStream);
istream = Tb_null;
Exit Ostream if (ostream) tb_stream_exit (ostream);
Ostream = Tb_null;
Exit option if (option) tb_option_exit (option);
option = Tb_null;
return 0; #else tb_int_t Tb_demo_stream_main (tb_int_t argc, tb_char_t** argv) {return 0;} #endif
The above is the entire contents of this article, I hope you can enjoy.