diff --git a/core/request.cpp b/core/request.cpp index b0f9a93..3f40592 100644 --- a/core/request.cpp +++ b/core/request.cpp @@ -59,6 +59,28 @@ void Request::send() { RequestPool::return_request(this); } +void Request::send_file(const std::string &p_file_path) { + file_path = p_file_path; + + FILE *f = fopen(file_path.c_str(), "rb"); + + if (!f) { + printf("send_file: Error: Download: file doesn't exists! %s\n", file_path.c_str()); + + return; + } + + fseek(f, 0, SEEK_END); + file_size = ftell(f); + fclose(f); + + response->addHeadValue("Connection", "Close"); + std::string result = "HTTP/1.1 200 OK\r\nConnection: Close\r\n\r\n"; + const HttpSession::Ptr lsession = (*session); + + (*session)->send(result.c_str(), result.size(), [this]() { this->_progress_send_file(); }); +} + void Request::reset() { http_parser = nullptr; session = nullptr; @@ -66,6 +88,8 @@ void Request::reset() { middleware_stack = nullptr; _path_stack.clear(); _path_stack_pointer = 0; + file_size = 0; + current_file_progress = 0; head.clear(); body.clear(); @@ -151,6 +175,8 @@ void Request::push_path() { Request::Request() { response = nullptr; + //file_chunk_size = 1 << 20; //1MB + file_chunk_size = 1 << 23; reset(); } @@ -159,6 +185,48 @@ Request::~Request() { delete response; } +void Request::_progress_send_file() { + const HttpSession::Ptr lsession = (*session); + + if (current_file_progress >= file_size) { + lsession->postShutdown(); + + RequestPool::return_request(this); + + return; + } + + FILE *f = fopen(file_path.c_str(), "rb"); + + if (!f) { + printf("Error: Download: In progress file doesn't exists anymore! %s\n", file_path.c_str()); + + lsession->postShutdown(); + + RequestPool::return_request(this); + + return; + } + + fseek(f, current_file_progress, SEEK_SET); + + long nfp = current_file_progress + file_chunk_size; + + long csize = file_chunk_size; + if (nfp >= file_size) { + csize = (file_size - current_file_progress); + } + + body.resize(csize); + + fread(&body[0], 1, csize, f); + fclose(f); + + current_file_progress = nfp; + + (*session)->send(body.c_str(), body.size(), [this]() { this->_progress_send_file(); }); +} + Request *RequestPool::get_request() { _mutex.lock(); diff --git a/core/request.h b/core/request.h index c5297a2..e6d0352 100644 --- a/core/request.h +++ b/core/request.h @@ -28,10 +28,17 @@ public: std::string footer; std::string compiled_body; + std::string file_path; + long file_size; + long current_file_progress; + long file_chunk_size; + bool file_next; + void compile_body(); void compile_and_send_body(); void next_stage(); void send(); + void send_file(const std::string &p_file_path); void reset(); void setup_url_stack(); @@ -49,6 +56,8 @@ public: ~Request(); protected: + void _progress_send_file(); + std::vector _path_stack; uint32_t _path_stack_pointer; }; diff --git a/modules/paged_article/paged_article.cpp b/modules/paged_article/paged_article.cpp index 96dd95f..04e1845 100644 --- a/modules/paged_article/paged_article.cpp +++ b/modules/paged_article/paged_article.cpp @@ -30,29 +30,7 @@ void PagedArticle::index(Request *request) { if (s->file_cache->wwwroot_has_file(file_name)) { std::string fp = s->file_cache->wwwroot + file_name; - FILE *f = fopen(fp.c_str(), "rb"); - - if (!f) { - printf("Error: Registered file doesn't exists anymore! %s\n", fp.c_str()); - - Application::get_instance()->send_error(404, request); - return; - } - - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - fseek(f, 0, SEEK_SET); /* same as rewind(f); */ - - std::string body; - body.resize(fsize); - - fread(&body[0], 1, fsize, f); - fclose(f); - - //TODO set mimetype? - - request->response->setBody(body); - request->send(); + request->send_file(fp); return; } }