diff --git a/.gitignore b/.gitignore index 1d36f897..f02f7e97 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,4 @@ CMakeUserPresets.json .DS_Store node_modules /CMakeSettings.json +!cmake/build.cmake diff --git a/README.md b/README.md index fd6cfb3e..b7bc5538 100644 --- a/README.md +++ b/README.md @@ -246,6 +246,20 @@ cinatra目前支持了multipart和octet-stream格式的上传。 //chunked download //cinatra will send you the file, if the file is big file(more than 5M) the file will be downloaded by chunked. support continues download + 同时可以使用set_http_file_server(std::string path);函数来将cinatra转换为一个http文件下载服务器,path为该文件服务器的路径。示例如下: + + #include "cinatra.hpp" + using namespace cinatra; + + int main() { + http_server server(std::thread::hardware_concurrency()); + server.set_http_file_server("http_file_server"); + server.listen("0.0.0.0", "8080"); + // 略 + } + + 此时访问当前服务器的`http_file_server`路径时会在浏览器展示所有可下载文件,点击即可下载。 + ## 示例6:websocket #include "cinatra.hpp" diff --git a/example/main.cpp b/example/main.cpp index 87f85ad6..741497c9 100644 --- a/example/main.cpp +++ b/example/main.cpp @@ -242,6 +242,7 @@ int main() { // test_ssl_server(); // test_download(); http_server server(std::thread::hardware_concurrency()); + server.set_http_file_server("http_download_file_server"); bool r = server.listen("0.0.0.0", "8090"); if (!r) { // LOG_INFO << "listen failed"; diff --git a/include/cinatra/http_server.hpp b/include/cinatra/http_server.hpp index ce9ea845..35b50429 100644 --- a/include/cinatra/http_server.hpp +++ b/include/cinatra/http_server.hpp @@ -174,6 +174,10 @@ class http_server_ : private noncopyable { set_file_dir(std::move(path), upload_dir_); } + void set_http_file_server(std::string path) { + download_display_file_dir_ = path; + } + const std::string &static_dir() const { return static_dir_; } // xM @@ -346,6 +350,16 @@ class http_server_ : private noncopyable { } } + if (!download_display_file_dir_.empty()) { + std::string ret = ""; + bool is_need_download_lists_response = + build_http_download_lists_response(req, std::move(ret)); + if (is_need_download_lists_response) { + res.set_status_and_content(status_type::ok, std::move(ret)); + return; + } + } + auto state = req.get_state(); switch (state) { case cinatra::data_proc_state::data_begin: { @@ -587,6 +601,35 @@ class http_server_ : private noncopyable { } } + bool build_http_download_lists_response(request &req, + std::string &&resp_str) { + std::string res_str = ""; + std::string href_of_head = "
"; + if (req.get_res_path() == download_display_file_dir_) { + std::string file_dir_str = static_dir_; + std::filesystem::path dir_path(file_dir_str); + + for (const auto &entry : std::filesystem::directory_iterator(dir_path)) { + if (!entry.is_directory()) { + auto u8_file_name = entry.path().filename().u8string(); + std::string file_name_str(u8_file_name.begin(), u8_file_name.end()); + std::string full_href = href_of_head + file_name_str + href_of_tail + + file_name_str + "
"; + res_str += full_href; + } + } + std::string ret = + download_dir_response_head_ + res_str + download_dir_response_tail_; + resp_str = std::move(ret); + return true; + } + else { + return false; + } + } + service_pool_policy io_service_pool_; std::size_t max_req_buf_size_ = @@ -596,6 +639,7 @@ class http_server_ : private noncopyable { http_router http_router_; std::string static_dir_ = fs::absolute("www").string(); // default std::string upload_dir_ = fs::absolute("www").string(); // default + std::string download_display_file_dir_ = ""; std::time_t static_res_cache_max_age_ = 0; bool enable_timeout_ = true; @@ -620,6 +664,15 @@ class http_server_ : private noncopyable { uint64_t conn_id_ = 0; std::unordered_map>> conns_; std::mutex conns_mtx_; + + std::string download_dir_response_head_ = + "" + "http file download " + "server" + ""; + std::string download_dir_response_tail_ = + "" + ""; }; template diff --git a/lang/english/README.md b/lang/english/README.md index dc2146a0..744f830a 100644 --- a/lang/english/README.md +++ b/lang/english/README.md @@ -248,6 +248,22 @@ http://127.0.0.1:8080/purecpp/static/show.jpg //cinatra will send you the file, if the file is big file(more than 5M) the file will be downloaded by chunked. support continues download ``` +At the same time, you can use the `set_http_file_server(std::string path);` function to build an http file download server. The parameter path is the path of all downloadable files. Examples are as follows: + +```cpp +#include "cinatra.hpp" +using namespace cinatra; + +int main() { + http_server server(std::thread::hardware_concurrency()); + server.set_http_file_server("http_file_server"); + server.listen("0.0.0.0", "8080"); + // ...... +} +``` + +In this time, when accessing the `http_file_server` path of the current server, all downloadable files will be displayed in the browser, and you can download them by clicking on them. + ### Example 6: WebSocket ```cpp