diff --git a/include/ylt/standalone/cinatra/coro_http_client.hpp b/include/ylt/standalone/cinatra/coro_http_client.hpp index 02fa4bf5d..684615187 100644 --- a/include/ylt/standalone/cinatra/coro_http_client.hpp +++ b/include/ylt/standalone/cinatra/coro_http_client.hpp @@ -878,7 +878,8 @@ class coro_http_client : public std::enable_shared_from_this { } async_simple::coro::Lazy send_file_no_chunked_with_copy( - std::string_view source, std::error_code &ec, std::size_t length) { + std::string_view source, std::error_code &ec, std::size_t length, + std::size_t offset) { if (length <= 0) { co_return; } @@ -886,6 +887,7 @@ class coro_http_client : public std::enable_shared_from_this { detail::resize(file_data, std::min(max_single_part_size_, length)); coro_io::coro_file file{}; file.open(source, std::ios::in); + file.seek(offset, std::ios::cur); if (!file.is_open()) { ec = std::make_error_code(std::errc::bad_file_descriptor); co_return; @@ -923,15 +925,15 @@ class coro_http_client : public std::enable_shared_from_this { }; async_simple::coro::Lazy send_file_without_copy( const std::filesystem::path &source, std::error_code &ec, - std::size_t length) { + std::size_t length, std::size_t offset) { fd_guard guard(source.c_str()); if (guard.fd < 0) [[unlikely]] { ec = std::make_error_code(std::errc::bad_file_descriptor); co_return; } std::size_t actual_len = 0; - std::tie(ec, actual_len) = - co_await coro_io::async_sendfile(socket_->impl_, guard.fd, 0, length); + std::tie(ec, actual_len) = co_await coro_io::async_sendfile( + socket_->impl_, guard.fd, offset, length); if (ec) [[unlikely]] { co_return; } @@ -1009,7 +1011,8 @@ class coro_http_client : public std::enable_shared_from_this { template async_simple::coro::Lazy async_upload( S uri, http_method method, Source source /* file */, - int64_t content_length = -1, + uint64_t offset = 0 /*file offset*/, + int64_t content_length = -1 /*upload size*/, req_content_type content_type = req_content_type::text, std::unordered_map headers = {}) { std::error_code ec{}; @@ -1053,6 +1056,12 @@ class coro_http_client : public std::enable_shared_from_this { co_return resp_data{std::make_error_code(std::errc::invalid_argument), 404}; } + content_length -= offset; + if (content_length < 0) { + CINATRA_LOG_ERROR << "the offset is larger than the end of file"; + co_return resp_data{std::make_error_code(std::errc::invalid_argument), + 404}; + } } assert(content_length >= 0); @@ -1091,6 +1100,7 @@ class coro_http_client : public std::enable_shared_from_this { } if constexpr (is_stream_file) { + source->seekg(offset, std::ios::cur); std::string file_data; detail::resize(file_data, std::min(max_single_part_size_, content_length)); @@ -1119,15 +1129,17 @@ class coro_http_client : public std::enable_shared_from_this { if (!has_init_ssl_) { #endif co_await send_file_without_copy(std::filesystem::path{source}, ec, - content_length); + content_length, offset); #ifdef CINATRA_ENABLE_SSL } else { - co_await send_file_no_chunked_with_copy(source, ec, content_length); + co_await send_file_no_chunked_with_copy(source, ec, content_length, + offset); } #endif #else - co_await send_file_no_chunked_with_copy(source, ec, content_length); + co_await send_file_no_chunked_with_copy(source, ec, content_length, + offset); #endif } else {