- Notifications
You must be signed in to change notification settings - Fork1.3k
Description
Hello,
I'm trying to develop a large file (about 200MB) download functionality using FileStream as (I think) this is the only way of doing that without loading whole file into ram. The code below is for endpoint and file reader. The problem is, when I click a link on my frontend:
<a href="https://my-api/download-file" download>Download</a>
or when I'm doing ajax request, the file seems to be loaded into ram anyways.
top
before:
when clicking the downlaod link, it seems to be buffering for about 10 seconds until download file selector window appears,top
after this time:
The system is embedded device with linux and 512MB of RAM.oatpp-1.3.0
myController.hENDPOINT("GET", "api/someEndpoint", getData);
myController.cpp
shared_ptr<OutgoingResponse>MyController::getData()){ auto reader = std::make_shared<FileReadCallback>("/largeFile.log"); auto body = std::make_shared<oatpp::web::protocol::http::outgoing::StreamingBody>(reader); auto response = OutgoingResponse::createShared(Status::CODE_200, body); response->putHeader("Content-Disposition", "attachment; filename=testfile.log"); response->putHeader("Content-Type", "application/octet-stream"); response->putHeader("Content-Length", std::to_string(reader->getSize())); return response;}
I tried with multiple header combinations but no luck
FileReadCallback
class FileReadCallback : public oatpp::data::stream::ReadCallback { private: FILE* m_file; v_int64 m_progress; v_int64 m_size; public: FileReadCallback(const std::string& filename) : m_progress(0) { m_file = fopen(filename.c_str(), "rb"); // Open file in binary mode if (!m_file) { throw std::runtime_error("Failed to open file"); } // Get the file size fseek(m_file, 0, SEEK_END); m_size = ftell(m_file); fseek(m_file, 0, SEEK_SET); // Reset file pointer to the beginning } oatpp::v_io_size read(void *buffer, v_buff_size count, oatpp::async::Action& action) override { if (m_progress >= m_size) { return 0; // No more data to read } size_t bytesRead = fread(buffer, 1, count, m_file); if (bytesRead > 0) { m_progress += bytesRead; return static_cast<oatpp::v_io_size>(bytesRead); // Return the number of bytes read } return 0; } v_int64 getSize() { return m_size; } ~FileReadCallback() { if (m_file) { fclose(m_file); // Close the file } }};