#pragma once #include "../acl_cpp_define.hpp" #include "../stdlib/noncopyable.hpp" namespace acl { class http_client; class http_request; class http_header; class ACL_CPP_API http_download : public noncopyable { public: /** * 构造函数 * @param url {const char*} 文件在服务器上的 url 地址 * @param addr {const char*} 非空时,设置服务器地址(格式为: * ip[|domain]:port,否则服务器地址从 url 中提取 */ http_download(const char* url, const char* addr = NULL); virtual ~http_download(); /** * 在调用 run 之前可以通过本函数获得请求头对象,便于用户设置 * 自己的请求头字段(但 set_method/set_range 是内部自动设置的) * @return {http_header*} 返回 NULL 表示输入的 URL 非法 */ http_header* request_header() const; /** * 调用此函数可以获得 http_request 对象,便于设置或查询请求头 * 或返回数据中的参数 * @return {http_request*} 返回 NULL 表示输入的 URL 非法 */ http_request* request() const; /** * 下载文件,当 range_from >= 0 且 range_to >= range_from 时自动 * 采用分段下载方式,否则采用全部下载方式 * @param range_from {acl_int64} 下载起始偏移位置,下标从 0 开始, * 当该值 >= 0 且 range_to >= 本值时才采用分段下载方式 * @param range_to {acl_int64} 下载结束偏移位置 * @param req_body {const char*} 请求的数据体 * @param len {size_t} req_body 非空时指明其长度 * @return {bool} 下载是否成功,如果返回 true 则表示下载成功,否则 * 可能是输入参数非法,或 URL 不存在,或服务器不支持断点传输,或 * 在下载过程中子类返回 false 禁止继续下载 */ #if defined(_WIN32) || defined(_WIN64) bool get(__int64 range_from = -1, __int64 range_to = -1, const char* req_body = NULL, size_t len = 0); #else bool get(long long int range_from = -1, long long int range_to = -1, const char* req_body = NULL, size_t len = 0); #endif /** * 重置内部请求状态 * @param url {const char*} 非空时则用此 URL 替代构造函数中输入的 URL, * 否则依然使用构造函数中使用的 url * @param addr {const char*} 非空时,设置服务器地址(格式为: * ip[|domain]:port,否则服务器地址从 url 中提取 * @return {bool} 返回 false 表示 url 非法 */ bool reset(const char* url = NULL, const char* addr = NULL); /** * 取得由构造函数或 reset 函数输入的 url * @return {const char*} 返回 NULL 表示输入的 url 非法 */ const char* get_url() const; /** * 取得由构造函数或 reset 函数输入的 url 所得到的服务器地址,格式为: * ip[|domain]:port * @return {const char*} 返回 NULL 表示输入的 url 非法 */ const char* get_addr() const; protected: /** * 当发送完 HTTP 请求数据后,读到 HTTP 服务器响应头后的回调函数 * @param conn {http_client*} * @return {bool} 若子类返回 false 则停止继续下载 */ virtual bool on_response(http_client* conn); /** * 当得到服务器返回完整文件长度后的回调函数 * @param n {__int64} 完整文件长度 * @return {bool} 若子类返回 false 则停止继续下载 */ #if defined(_WIN32) || defined(_WIN64) virtual bool on_length(__int64 n); #else virtual bool on_length(long long int n); #endif /** * 下载过程中,边下载边通知子类下载的数据及数据长度 * @param data {const void*} 下载的数据地址 * @param len {size_t} 下载的数据长度 * @return {bool} 若子类返回 false 则停止继续下载 */ virtual bool on_save(const void* data, size_t len) = 0; private: char* url_; char addr_[128]; http_request* req_; // 从头开始下载整个文件 bool save_total(const char* body, size_t len); // 断点下载部分文件 #if defined(_WIN32) || defined(_WIN64) bool save_range(const char* body, size_t len, __int64 range_from, __int64 range_to); #else bool save_range(const char* body, size_t len, long long int range_from, long long int range_to); #endif // 开始下载 bool save(http_request* req); }; } // namespace acl